svvitch
digital signage player
|
00001 #include "VideoTextureAllocator.h" 00002 #include <Poco/format.h> 00003 #include <Poco/UUID.h> 00004 00005 VideoTextureAllocator::VideoTextureAllocator(Renderer& renderer): 00006 _log(Poco::Logger::get("")), _refCount(0), _renderer(renderer), _texture(NULL), _presenting(false) 00007 { 00008 } 00009 00010 VideoTextureAllocator::‾VideoTextureAllocator() { 00011 } 00012 00013 LPDIRECT3DTEXTURE9 VideoTextureAllocator::getTexture() { 00014 return _texture; 00015 } 00016 00017 float VideoTextureAllocator::getDisplayAspectRatio() { 00018 if (_h > 0) return F(_w) / _h; 00019 return 1; 00020 } 00021 00022 00023 // IVMRSurfaceAllocator9 00024 HRESULT VideoTextureAllocator::InitializeDevice(DWORD_PTR userID, VMR9AllocationInfo* info, DWORD* buffers) { 00025 if (buffers == NULL || info == NULL) return E_POINTER; 00026 00027 _log.information(Poco::format("** initialize device %lu %lu", userID, ((DWORD)info->Format))); 00028 string s = Poco::format("aspect:%ld/%ld native:%ldx%ld", info->szAspectRatio.cx, info->szAspectRatio.cy, info->szNativeSize.cx, info->szNativeSize.cy); 00029 _log.information(Poco::format("** initialize device(%lu) format:%lu %lux%lu(%s) x %lu", userID, ((DWORD)info->Format), info->dwWidth, info->dwHeight, s, *buffers)); 00030 D3DFORMAT format = D3DFMT_A8R8G8B8; 00031 LPDIRECT3DTEXTURE9 texture = NULL; 00032 switch (info->dwFlags) { 00033 case VMR9AllocFlag_3DRenderTarget: 00034 texture = _renderer.createRenderTarget(info->dwWidth, info->dwHeight, format); 00035 break; 00036 default: 00037 _log.warning(Poco::format("failed not initialize flag: %lu", info->dwFlags)); 00038 } 00039 if (texture) { 00040 Poco::ScopedLock<Poco::FastMutex> lock(_lock); 00041 SAFE_RELEASE(_texture); 00042 _texture = texture; 00043 _log.information(Poco::format("texture ready %lux%lu", info->dwWidth, info->dwHeight)); 00044 return S_OK; 00045 } 00046 return E_FAIL; 00047 } 00048 00049 HRESULT VideoTextureAllocator::TerminateDevice(DWORD_PTR userID) { 00050 _log.information("** terminate device"); 00051 Poco::ScopedLock<Poco::FastMutex> lock(_lock); 00052 SAFE_RELEASE(_texture); 00053 return S_OK; 00054 } 00055 00056 HRESULT VideoTextureAllocator::GetSurface(DWORD_PTR userID, DWORD index, DWORD surfaceFlags, LPDIRECT3DSURFACE9* surface) { 00057 Poco::ScopedLock<Poco::FastMutex> lock(_lock); 00058 if (!_texture) return E_FAIL; 00059 if (surface == NULL) { 00060 _log.warning(Poco::format("no surface: %lu", userID)); 00061 return E_POINTER; 00062 } 00063 00064 if (index >= 1) { 00065 _log.warning(Poco::format("outOfIndex:%lu flags:%lu", userID, surfaceFlags)); 00066 Sleep(5000); 00067 return E_FAIL; 00068 } 00069 00070 HRESULT hr = E_FAIL; 00071 hr = _texture->GetSurfaceLevel(0, surface); 00072 if FAILED(hr) { 00073 _log.warning("** failed get surface"); 00074 return hr; 00075 } 00076 00077 //while (surface && _presenting && _renderer.peekMessage() && !_renderer.tryDrawLock()) { 00078 // // block 00079 // Sleep(0); 00080 //} 00081 return hr; 00082 } 00083 00084 HRESULT VideoTextureAllocator::AdviseNotify(IVMRSurfaceAllocatorNotify9* surfAllocNotify) { 00085 _log.information("** advise notify"); 00086 IDirect3D9 *d3d = NULL; 00087 _renderer.get3DDevice()->GetDirect3D(&d3d); 00088 HMONITOR monitor = d3d->GetAdapterMonitor(D3DADAPTER_DEFAULT); 00089 d3d->Release(); 00090 HRESULT hr = surfAllocNotify->SetD3DDevice(_renderer.get3DDevice(), monitor); 00091 if (FAILED(hr)) { 00092 _log.information("failed SetD3DDevice()"); 00093 return hr; 00094 } 00095 return S_OK; 00096 } 00097 00098 00099 // IVMRImagePresenter9 00100 HRESULT VideoTextureAllocator::StartPresenting(DWORD_PTR userID) { 00101 _log.information("** start presenting"); 00102 _presenting = true; 00103 return S_OK; 00104 } 00105 00106 HRESULT VideoTextureAllocator::StopPresenting(DWORD_PTR userID) { 00107 _log.information("** stop presenting"); 00108 _presenting = false; 00109 return S_OK; 00110 } 00111 00112 HRESULT VideoTextureAllocator::PresentImage(DWORD_PTR userID, VMR9PresentationInfo *info) { 00113 // レンダリング可能状態 00114 //_renderer.drawUnlock(); 00115 //D3DLOCKED_RECT locked_rect; 00116 //HRESULT hr =info->lpSurf->LockRect(&locked_rect, NULL, D3DLOCK_READONLY); 00117 //if SUCCEEDED(hr) { 00118 // hr = info->lpSurf->UnlockRect(); 00119 //} 00120 return S_OK; 00121 } 00122 00123 00124 // IVMRImageCompositor9 00125 HRESULT VideoTextureAllocator::InitCompositionDevice(IUnknown* pD3DDevice) { 00126 _log.information("** init composite device"); 00127 return S_OK; 00128 } 00129 00130 HRESULT VideoTextureAllocator::TermCompositionDevice(IUnknown* pD3DDevice) { 00131 _log.information("** term composite device"); 00132 return S_OK; 00133 } 00134 00135 HRESULT VideoTextureAllocator::SetStreamMediaType(DWORD streamID, AM_MEDIA_TYPE* pmt, BOOL fTexture) { 00136 if (pmt == NULL) { 00137 _w = 0; 00138 _h = 0; 00139 return S_OK; 00140 } 00141 00142 if (pmt->majortype != MEDIATYPE_Video) { 00143 _log.warning("** failed AM_MEDIA_TYPE not video"); 00144 return E_FAIL; 00145 } 00146 00147 string formatType; 00148 string subType; 00149 long w = 0; 00150 long h = 0; 00151 LONGLONG tpf = 0; 00152 if (pmt->formattype == FORMAT_VideoInfo) { 00153 VIDEOINFOHEADER* vih = reinterpret_cast<VIDEOINFOHEADER*>(pmt->pbFormat); 00154 //_isInterlaced = false; 00155 tpf = vih->AvgTimePerFrame; 00156 w = vih->bmiHeader.biWidth; 00157 h = vih->bmiHeader.biHeight; 00158 if (h < 0) h = -h; 00159 formatType = "VideoInfo"; 00160 } else if (pmt->formattype == FORMAT_VideoInfo2) { 00161 VIDEOINFOHEADER2* vih = reinterpret_cast<VIDEOINFOHEADER2*>(pmt->pbFormat); 00162 //_isInterlaced = (vih->dwInterlaceFlags & AMINTERLACE_IsInterlaced) != 0; 00163 tpf = vih->AvgTimePerFrame; 00164 w = vih->bmiHeader.biWidth; 00165 h = vih->bmiHeader.biHeight; 00166 if (h < 0) h = -h; 00167 formatType = "VideoInfo2"; 00168 } 00169 00170 D3DFORMAT format = D3DFMT_X8R8G8B8; 00171 HRESULT hr = E_FAIL; 00172 if (pmt->subtype == MEDIASUBTYPE_YUY2 || pmt->subtype == MEDIASUBTYPE_YUYV) { 00173 subType = "YUY2/YUYV"; 00174 //_timePerFrames = tpf; 00175 format = D3DFMT_YUY2; 00176 hr = S_OK; 00177 } else if (pmt->subtype == MEDIASUBTYPE_IYUV) { 00178 subType = "IYUV"; 00179 //_timePerFrames = tpf; 00180 format = D3DFMT_UYVY; 00181 // hr = S_OK; 00182 } else if (pmt->subtype == MEDIASUBTYPE_Y41P) { 00183 subType = "Y41P"; 00184 //_timePerFrames = tpf; 00185 format = D3DFMT_UYVY; 00186 // hr = S_OK; 00187 } else if (pmt->subtype == MEDIASUBTYPE_UYVY) { 00188 subType = "UYVY"; 00189 //_timePerFrames = tpf; 00190 format = D3DFMT_UYVY; 00191 hr = S_OK; 00192 } else if (pmt->subtype == MEDIASUBTYPE_YVYU) { 00193 subType = "YVYU"; 00194 //_timePerFrames = tpf; 00195 format = D3DFMT_UYVY; 00196 hr = S_OK; 00197 } else if (pmt->subtype == MEDIASUBTYPE_RGB565) { 00198 subType = "RGB565"; 00199 //_timePerFrames = tpf; 00200 format = D3DFMT_R5G6B5; 00201 hr = S_OK; 00202 } else if (pmt->subtype == MEDIASUBTYPE_RGB555) { 00203 subType = "RGB555"; 00204 //_timePerFrames = tpf; 00205 format = D3DFMT_X1R5G5B5; 00206 hr = S_OK; 00207 } else if (pmt->subtype == MEDIASUBTYPE_RGB24) { 00208 subType = "RGB24"; 00209 //_timePerFrames = tpf; 00210 format = D3DFMT_R8G8B8; 00211 hr = S_OK; 00212 } else if (pmt->subtype == MEDIASUBTYPE_RGB32) { 00213 subType = "RGB32"; 00214 format = D3DFMT_X8R8G8B8; 00215 //_timePerFrames = tpf; 00216 hr = S_OK; 00217 } else if (pmt->subtype == MEDIASUBTYPE_ARGB32) { 00218 subType = "ARGB32"; 00219 //_timePerFrames = tpf; 00220 format = D3DFMT_A8R8G8B8; 00221 hr = S_OK; 00222 } else { 00223 // UuidToString(&pmt->subtype, (unsigned short**)&subType); 00224 string serial; 00225 for (int i = 0; i < 8; i++) { 00226 serial += Poco::format(",%02?x", pmt->subtype.Data4[i]); 00227 } 00228 subType = Poco::format("unknown[%08?x,%04?x,%04?x%s]", pmt->subtype.Data1, pmt->subtype.Data2, pmt->subtype.Data3, serial); 00229 //_timePerFrames = tpf; 00230 // hr = S_OK; 00231 } 00232 _log.information(Poco::format("allocator format[%s] stream[%s] %ldx%ld(%.2hf) [%s]", formatType, subType, w, h, (F(10000000) / tpf), string(fTexture == TRUE?"texture":"not texture"))); 00233 00234 if (SUCCEEDED(hr) && (_w != w || _h != h || _format != format) && _h == 0) { 00235 // サイズ変化があり、_h=0 ならテクスチャを再生成します 00236 LPDIRECT3DTEXTURE9 texture = _renderer.createRenderTarget(w, h, format); 00237 if (texture) { 00238 Poco::ScopedLock<Poco::FastMutex> lock(_lock); 00239 SAFE_RELEASE(_texture); 00240 _texture = texture; 00241 _log.information(Poco::format("size/format changed, create texture %dx%d %x", w, h, format)); 00242 } 00243 } 00244 _w = w; 00245 _h = h; 00246 _format = format; 00247 return hr; 00248 } 00249 00250 HRESULT VideoTextureAllocator::CompositeImage(IUnknown* pD3DDevice, IDirect3DSurface9* rt, AM_MEDIA_TYPE* pmt, REFERENCE_TIME start, REFERENCE_TIME end, D3DCOLOR background, VMR9VideoStreamInfo* info, UINT streams) { 00251 LPDIRECT3DDEVICE9 device = _renderer.get3DDevice(); 00252 HRESULT hr; 00253 //LPDIRECT3DSWAPCHAIN9 swapChain = NULL; 00254 //hr = device->GetSwapChain(0, &swapChain); 00255 //if SUCCEEDED(hr) { 00256 // LPDIRECT3DSURFACE9 backBuffer = NULL; //バックバッファ 00257 // hr = swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backBuffer); 00258 // hr = device->SetRenderTarget(0, backBuffer); 00259 // SAFE_RELEASE(backBuffer); 00260 // SAFE_RELEASE(swapChain); 00261 //} 00262 00263 hr = device->StretchRect(info->pddsVideoSurface, NULL, rt, NULL, D3DTEXF_NONE); 00264 return S_OK; 00265 } 00266 00267 00268 // IUnknown 00269 HRESULT VideoTextureAllocator::QueryInterface(REFIID riid, void** ppvObject) { 00270 HRESULT hr = E_NOINTERFACE; 00271 00272 if (ppvObject == NULL) { 00273 hr = E_POINTER; 00274 00275 } else if (riid == IID_IVMRSurfaceAllocator9) { 00276 *ppvObject = static_cast<IVMRSurfaceAllocator9*>(this); 00277 AddRef(); 00278 hr = S_OK; 00279 00280 } else if (riid == IID_IVMRImagePresenter9) { 00281 *ppvObject = static_cast<IVMRImagePresenter9*>(this); 00282 AddRef(); 00283 hr = S_OK; 00284 00285 } else if (riid == IID_IVMRImageCompositor9) { 00286 *ppvObject = static_cast<IVMRImageCompositor9*>(this); 00287 AddRef(); 00288 hr = S_OK; 00289 00290 } else if (riid == IID_IUnknown) { 00291 *ppvObject = static_cast<IUnknown*>(static_cast<IVMRSurfaceAllocator9*>(this)); 00292 AddRef(); 00293 hr = S_OK; 00294 } 00295 00296 return hr; 00297 } 00298 00299 ULONG VideoTextureAllocator::AddRef() { 00300 return InterlockedIncrement(&_refCount); 00301 } 00302 00303 ULONG VideoTextureAllocator::Release() { 00304 ULONG ret = InterlockedDecrement(&_refCount); 00305 if (ret == 0) delete this; 00306 return ret; 00307 }