svvitch
digital signage player
D:/vs_workspace/switch_sf/src/svvitch/VideoTextureAllocator.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines