diff options
Diffstat (limited to 'plugins/pluginWinMF/plugin_win_mf_consumer_video.cxx')
-rwxr-xr-x | plugins/pluginWinMF/plugin_win_mf_consumer_video.cxx | 2151 |
1 files changed, 1039 insertions, 1112 deletions
diff --git a/plugins/pluginWinMF/plugin_win_mf_consumer_video.cxx b/plugins/pluginWinMF/plugin_win_mf_consumer_video.cxx index f6bef59..ee6eaaa 100755 --- a/plugins/pluginWinMF/plugin_win_mf_consumer_video.cxx +++ b/plugins/pluginWinMF/plugin_win_mf_consumer_video.cxx @@ -1,18 +1,18 @@ /* Copyright (C) 2013 Mamadou DIOP * Copyright (C) 2013 Doubango Telecom <http://www.doubango.org> -* +* * This file is part of Open Source Doubango Framework. * * DOUBANGO is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. -* +* * DOUBANGO is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. -* +* * You should have received a copy of the GNU General Public License * along with DOUBANGO. */ @@ -50,20 +50,20 @@ const DWORD NUM_BACK_BUFFERS = 2; static HRESULT CreateDeviceD3D9( - HWND hWnd, - IDirect3DDevice9** ppDevice, - IDirect3D9 **ppD3D, - D3DPRESENT_PARAMETERS &d3dpp - ); + HWND hWnd, + IDirect3DDevice9** ppDevice, + IDirect3D9 **ppD3D, + D3DPRESENT_PARAMETERS &d3dpp +); static HRESULT TestCooperativeLevel( - struct plugin_win_mf_consumer_video_s *pSelf - ); + struct plugin_win_mf_consumer_video_s *pSelf +); static HRESULT CreateSwapChain( - HWND hWnd, - UINT32 nFrameWidth, - UINT32 nFrameHeight, - IDirect3DDevice9* pDevice, - IDirect3DSwapChain9 **ppSwapChain); + HWND hWnd, + UINT32 nFrameWidth, + UINT32 nFrameHeight, + IDirect3DDevice9* pDevice, + IDirect3DSwapChain9 **ppSwapChain); static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); @@ -81,30 +81,29 @@ static HRESULT UnhookWindow(struct plugin_win_mf_consumer_video_s *pSelf); -typedef struct plugin_win_mf_consumer_video_s -{ - TMEDIA_DECLARE_CONSUMER; - - BOOL bStarted, bPrepared, bPaused, bFullScreen, bWindowHooked; - BOOL bPluginFireFox, bPluginWebRTC4All; - HWND hWindow; - WNDPROC wndProc; - HWND hWindowFullScreen; - RECT rcWindow; - RECT rcDest; - MFRatio pixelAR; - - UINT32 nNegWidth; - UINT32 nNegHeight; - UINT32 nNegFps; - - D3DLOCKED_RECT rcLock; - IDirect3DDevice9* pDevice; - IDirect3D9 *pD3D; - IDirect3DSwapChain9 *pSwapChain; - D3DPRESENT_PARAMETERS d3dpp; - - TSK_DECLARE_SAFEOBJ; +typedef struct plugin_win_mf_consumer_video_s { + TMEDIA_DECLARE_CONSUMER; + + BOOL bStarted, bPrepared, bPaused, bFullScreen, bWindowHooked; + BOOL bPluginFireFox, bPluginWebRTC4All; + HWND hWindow; + WNDPROC wndProc; + HWND hWindowFullScreen; + RECT rcWindow; + RECT rcDest; + MFRatio pixelAR; + + UINT32 nNegWidth; + UINT32 nNegHeight; + UINT32 nNegFps; + + D3DLOCKED_RECT rcLock; + IDirect3DDevice9* pDevice; + IDirect3D9 *pD3D; + IDirect3DSwapChain9 *pSwapChain; + D3DPRESENT_PARAMETERS d3dpp; + + TSK_DECLARE_SAFEOBJ; } plugin_win_mf_consumer_video_t; @@ -113,360 +112,331 @@ static int _plugin_win_mf_consumer_video_unprepare(plugin_win_mf_consumer_video_ /* ============ Media Consumer Interface ================= */ static int plugin_win_mf_consumer_video_set(tmedia_consumer_t *self, const tmedia_param_t* param) { - int ret = 0; - HRESULT hr = S_OK; - plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; - - if(!self || !param) - { - TSK_DEBUG_ERROR("Invalid parameter"); - CHECK_HR(hr = E_POINTER); - } - - if(param->value_type == tmedia_pvt_int64) - { - if(tsk_striequals(param->key, "remote-hwnd")) - { - HWND hWnd = reinterpret_cast<HWND>((INT64)*((int64_t*)param->value)); - if(hWnd != pSelf->hWindow) - { - tsk_safeobj_lock(pSelf); // block consumer thread - pSelf->hWindow = hWnd; - if(pSelf->bPrepared) - { - hr = ResetDevice(pSelf); - } - tsk_safeobj_unlock(pSelf); // unblock consumer thread - } - } - } - else if(param->value_type == tmedia_pvt_int32) - { - if(tsk_striequals(param->key, "fullscreen")) - { - BOOL bFullScreen = !!*((int32_t*)param->value); - TSK_DEBUG_INFO("[MF video consumer] Full Screen = %d", bFullScreen); - CHECK_HR(hr = SetFullscreen(pSelf, bFullScreen)); - } - else if(tsk_striequals(param->key, "create-on-current-thead")) - { - // DSCONSUMER(self)->create_on_ui_thread = *((int32_t*)param->value) ? tsk_false : tsk_true; - } - else if(tsk_striequals(param->key, "plugin-firefox")) - { - pSelf->bPluginFireFox = (*((int32_t*)param->value) != 0); - } - else if(tsk_striequals(param->key, "plugin-webrtc4all")) - { - pSelf->bPluginWebRTC4All = (*((int32_t*)param->value) != 0); - } - } - - CHECK_HR(hr); + int ret = 0; + HRESULT hr = S_OK; + plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; + + if(!self || !param) { + TSK_DEBUG_ERROR("Invalid parameter"); + CHECK_HR(hr = E_POINTER); + } + + if(param->value_type == tmedia_pvt_int64) { + if(tsk_striequals(param->key, "remote-hwnd")) { + HWND hWnd = reinterpret_cast<HWND>((INT64)*((int64_t*)param->value)); + if(hWnd != pSelf->hWindow) { + tsk_safeobj_lock(pSelf); // block consumer thread + pSelf->hWindow = hWnd; + if(pSelf->bPrepared) { + hr = ResetDevice(pSelf); + } + tsk_safeobj_unlock(pSelf); // unblock consumer thread + } + } + } + else if(param->value_type == tmedia_pvt_int32) { + if(tsk_striequals(param->key, "fullscreen")) { + BOOL bFullScreen = !!*((int32_t*)param->value); + TSK_DEBUG_INFO("[MF video consumer] Full Screen = %d", bFullScreen); + CHECK_HR(hr = SetFullscreen(pSelf, bFullScreen)); + } + else if(tsk_striequals(param->key, "create-on-current-thead")) { + // DSCONSUMER(self)->create_on_ui_thread = *((int32_t*)param->value) ? tsk_false : tsk_true; + } + else if(tsk_striequals(param->key, "plugin-firefox")) { + pSelf->bPluginFireFox = (*((int32_t*)param->value) != 0); + } + else if(tsk_striequals(param->key, "plugin-webrtc4all")) { + pSelf->bPluginWebRTC4All = (*((int32_t*)param->value) != 0); + } + } + + CHECK_HR(hr); bail: - return SUCCEEDED(hr) ? 0 : -1; + return SUCCEEDED(hr) ? 0 : -1; } static int plugin_win_mf_consumer_video_prepare(tmedia_consumer_t* self, const tmedia_codec_t* codec) { - plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; - - if(!pSelf || !codec && codec->plugin){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if(pSelf->bPrepared){ - TSK_DEBUG_WARN("D3D9 video consumer already prepared"); - return -1; - } - - // FIXME: DirectShow requires flipping but not D3D9 - // The Core library always tries to flip when OSType==Win32. Must be changed - TMEDIA_CODEC_VIDEO(codec)->in.flip = tsk_false; - - HRESULT hr = S_OK; - HWND hWnd = Window(pSelf); - - TMEDIA_CONSUMER(pSelf)->video.fps = TMEDIA_CODEC_VIDEO(codec)->in.fps; - TMEDIA_CONSUMER(pSelf)->video.in.width = TMEDIA_CODEC_VIDEO(codec)->in.width; - TMEDIA_CONSUMER(pSelf)->video.in.height = TMEDIA_CODEC_VIDEO(codec)->in.height; - - if(!TMEDIA_CONSUMER(pSelf)->video.display.width){ - TMEDIA_CONSUMER(pSelf)->video.display.width = TMEDIA_CONSUMER(pSelf)->video.in.width; - } - if(!TMEDIA_CONSUMER(pSelf)->video.display.height){ - TMEDIA_CONSUMER(pSelf)->video.display.height = TMEDIA_CONSUMER(pSelf)->video.in.height; - } - - pSelf->nNegFps = TMEDIA_CONSUMER(pSelf)->video.fps; - pSelf->nNegWidth = (UINT32)TMEDIA_CONSUMER(pSelf)->video.display.width; - pSelf->nNegHeight = (UINT32)TMEDIA_CONSUMER(pSelf)->video.display.height; - - TSK_DEBUG_INFO("D3D9 video consumer: fps=%d, width=%d, height=%d", - pSelf->nNegFps, - pSelf->nNegWidth, - pSelf->nNegHeight); - - TMEDIA_CONSUMER(pSelf)->video.display.chroma = tmedia_chroma_rgb32; - TMEDIA_CONSUMER(pSelf)->decoder.codec_id = tmedia_codec_id_none; // means accept RAW fames - - // The window handle is not created until the call is connect (incoming only) - At least on Internet Explorer 10 - if(hWnd && !pSelf->bPluginWebRTC4All) - { - CHECK_HR(hr = CreateDeviceD3D9(hWnd, &pSelf->pDevice, &pSelf->pD3D, pSelf->d3dpp)); - CHECK_HR(hr = CreateSwapChain(hWnd, pSelf->nNegWidth, pSelf->nNegHeight, pSelf->pDevice, &pSelf->pSwapChain)); - } - else - { - if(hWnd && pSelf->bPluginWebRTC4All) - { - TSK_DEBUG_INFO("[MF consumer] HWND is defined but we detected webrtc4all...delaying D3D9 device creating until session get connected"); - } - else - { - TSK_DEBUG_WARN("Delaying D3D9 device creation because HWND is not defined yet"); - } - } - + plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; + + if(!pSelf || !codec && codec->plugin) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if(pSelf->bPrepared) { + TSK_DEBUG_WARN("D3D9 video consumer already prepared"); + return -1; + } + + // FIXME: DirectShow requires flipping but not D3D9 + // The Core library always tries to flip when OSType==Win32. Must be changed + TMEDIA_CODEC_VIDEO(codec)->in.flip = tsk_false; + + HRESULT hr = S_OK; + HWND hWnd = Window(pSelf); + + TMEDIA_CONSUMER(pSelf)->video.fps = TMEDIA_CODEC_VIDEO(codec)->in.fps; + TMEDIA_CONSUMER(pSelf)->video.in.width = TMEDIA_CODEC_VIDEO(codec)->in.width; + TMEDIA_CONSUMER(pSelf)->video.in.height = TMEDIA_CODEC_VIDEO(codec)->in.height; + + if(!TMEDIA_CONSUMER(pSelf)->video.display.width) { + TMEDIA_CONSUMER(pSelf)->video.display.width = TMEDIA_CONSUMER(pSelf)->video.in.width; + } + if(!TMEDIA_CONSUMER(pSelf)->video.display.height) { + TMEDIA_CONSUMER(pSelf)->video.display.height = TMEDIA_CONSUMER(pSelf)->video.in.height; + } + + pSelf->nNegFps = TMEDIA_CONSUMER(pSelf)->video.fps; + pSelf->nNegWidth = (UINT32)TMEDIA_CONSUMER(pSelf)->video.display.width; + pSelf->nNegHeight = (UINT32)TMEDIA_CONSUMER(pSelf)->video.display.height; + + TSK_DEBUG_INFO("D3D9 video consumer: fps=%d, width=%d, height=%d", + pSelf->nNegFps, + pSelf->nNegWidth, + pSelf->nNegHeight); + + TMEDIA_CONSUMER(pSelf)->video.display.chroma = tmedia_chroma_rgb32; + TMEDIA_CONSUMER(pSelf)->decoder.codec_id = tmedia_codec_id_none; // means accept RAW fames + + // The window handle is not created until the call is connect (incoming only) - At least on Internet Explorer 10 + if(hWnd && !pSelf->bPluginWebRTC4All) { + CHECK_HR(hr = CreateDeviceD3D9(hWnd, &pSelf->pDevice, &pSelf->pD3D, pSelf->d3dpp)); + CHECK_HR(hr = CreateSwapChain(hWnd, pSelf->nNegWidth, pSelf->nNegHeight, pSelf->pDevice, &pSelf->pSwapChain)); + } + else { + if(hWnd && pSelf->bPluginWebRTC4All) { + TSK_DEBUG_INFO("[MF consumer] HWND is defined but we detected webrtc4all...delaying D3D9 device creating until session get connected"); + } + else { + TSK_DEBUG_WARN("Delaying D3D9 device creation because HWND is not defined yet"); + } + } + bail: - pSelf->bPrepared = SUCCEEDED(hr); - return pSelf->bPrepared ? 0 : -1; + pSelf->bPrepared = SUCCEEDED(hr); + return pSelf->bPrepared ? 0 : -1; } static int plugin_win_mf_consumer_video_start(tmedia_consumer_t* self) { - plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; - - if(!pSelf){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if(pSelf->bStarted){ - TSK_DEBUG_INFO("D3D9 video consumer already started"); - return 0; - } - if(!pSelf->bPrepared){ - TSK_DEBUG_ERROR("D3D9 video consumer not prepared"); - return -1; - } - - HRESULT hr = S_OK; - - pSelf->bPaused = false; - pSelf->bStarted = true; - - return SUCCEEDED(hr) ? 0 : -1; + plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; + + if(!pSelf) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if(pSelf->bStarted) { + TSK_DEBUG_INFO("D3D9 video consumer already started"); + return 0; + } + if(!pSelf->bPrepared) { + TSK_DEBUG_ERROR("D3D9 video consumer not prepared"); + return -1; + } + + HRESULT hr = S_OK; + + pSelf->bPaused = false; + pSelf->bStarted = true; + + return SUCCEEDED(hr) ? 0 : -1; } static int plugin_win_mf_consumer_video_consume(tmedia_consumer_t* self, const void* buffer, tsk_size_t size, const tsk_object_t* proto_hdr) { - plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; + plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; - HRESULT hr = S_OK; - HWND hWnd = Window(pSelf); + HRESULT hr = S_OK; + HWND hWnd = Window(pSelf); - IDirect3DSurface9 *pSurf = NULL; + IDirect3DSurface9 *pSurf = NULL; IDirect3DSurface9 *pBB = NULL; - if(!pSelf) - { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; // because of the mutex lock do it here - } - - tsk_safeobj_lock(pSelf); - - if(!buffer || !size) - { - TSK_DEBUG_ERROR("Invalid parameter"); - CHECK_HR(hr = E_INVALIDARG); - } - - if(!pSelf->bStarted) - { - TSK_DEBUG_INFO("D3D9 video consumer not started"); - CHECK_HR(hr = E_FAIL); - } - - if(!hWnd) - { - TSK_DEBUG_INFO("Do not draw frame because HWND not set"); - goto bail; // not an error as the application can decide to set the HWND at any time - } - - if (!pSelf->bWindowHooked) - { - // Do not hook "hWnd" as it could be the fullscreen handle which is always hooked. - CHECK_HR(hr = HookWindow(pSelf, pSelf->hWindow)); - } - - if(!pSelf->pDevice || !pSelf->pD3D || !pSelf->pSwapChain) - { - if(pSelf->pDevice || pSelf->pD3D || pSelf->pSwapChain) - { - CHECK_HR(hr = E_POINTER); // They must be "all null" or "all valid" - } - - if(hWnd) - { - // means HWND was not set but defined now - pSelf->nNegWidth = (UINT32)TMEDIA_CONSUMER(pSelf)->video.in.width; - pSelf->nNegHeight = (UINT32)TMEDIA_CONSUMER(pSelf)->video.in.height; - - CHECK_HR(hr = CreateDeviceD3D9(hWnd, &pSelf->pDevice, &pSelf->pD3D, pSelf->d3dpp)); - CHECK_HR(hr = CreateSwapChain(hWnd, pSelf->nNegWidth, pSelf->nNegHeight, pSelf->pDevice, &pSelf->pSwapChain)); - } - } - - if(pSelf->nNegWidth != TMEDIA_CONSUMER(pSelf)->video.in.width || pSelf->nNegHeight != TMEDIA_CONSUMER(pSelf)->video.in.height){ - TSK_DEBUG_INFO("Negotiated and input video sizes are different:%d#%d or %d#%d", - pSelf->nNegWidth, TMEDIA_CONSUMER(pSelf)->video.in.width, - pSelf->nNegHeight, TMEDIA_CONSUMER(pSelf)->video.in.height); - // Update media type - - SafeRelease(&pSelf->pSwapChain); - CHECK_HR(hr = CreateSwapChain(hWnd, (UINT32)TMEDIA_CONSUMER(pSelf)->video.in.width, (UINT32)TMEDIA_CONSUMER(pSelf)->video.in.height, pSelf->pDevice, &pSelf->pSwapChain)); - - pSelf->nNegWidth = (UINT32)TMEDIA_CONSUMER(pSelf)->video.in.width; - pSelf->nNegHeight = (UINT32)TMEDIA_CONSUMER(pSelf)->video.in.height; - - // Update Destination will do noting if the window size haven't changed. - // Force updating the destination rect if negotiated size change - CHECK_HR(hr = UpdateDestinationRect(pSelf, TRUE/* Force */)); - } - - CHECK_HR(hr = TestCooperativeLevel(pSelf)); - - CHECK_HR(hr = UpdateDestinationRect(pSelf)); - - CHECK_HR(hr = pSelf->pSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pSurf)); - CHECK_HR(hr = pSurf->LockRect(&pSelf->rcLock, NULL, D3DLOCK_NOSYSLOCK )); - - // Fast copy() using MMX, SSE, or SSE2 - hr = MFCopyImage( - (BYTE*)pSelf->rcLock.pBits, - pSelf->rcLock.Pitch, - (BYTE*)buffer, - (pSelf->nNegWidth << 2), - (pSelf->nNegWidth << 2), - pSelf->nNegHeight - ); - if(FAILED(hr)) - { - // unlock() before leaving - pSurf->UnlockRect(); - CHECK_HR(hr); - } - - CHECK_HR(hr = pSurf->UnlockRect()); - - // Color fill the back buffer - CHECK_HR(hr = pSelf->pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBB)); + if(!pSelf) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; // because of the mutex lock do it here + } + + tsk_safeobj_lock(pSelf); + + if(!buffer || !size) { + TSK_DEBUG_ERROR("Invalid parameter"); + CHECK_HR(hr = E_INVALIDARG); + } + + if(!pSelf->bStarted) { + TSK_DEBUG_INFO("D3D9 video consumer not started"); + CHECK_HR(hr = E_FAIL); + } + + if(!hWnd) { + TSK_DEBUG_INFO("Do not draw frame because HWND not set"); + goto bail; // not an error as the application can decide to set the HWND at any time + } + + if (!pSelf->bWindowHooked) { + // Do not hook "hWnd" as it could be the fullscreen handle which is always hooked. + CHECK_HR(hr = HookWindow(pSelf, pSelf->hWindow)); + } + + if(!pSelf->pDevice || !pSelf->pD3D || !pSelf->pSwapChain) { + if(pSelf->pDevice || pSelf->pD3D || pSelf->pSwapChain) { + CHECK_HR(hr = E_POINTER); // They must be "all null" or "all valid" + } + + if(hWnd) { + // means HWND was not set but defined now + pSelf->nNegWidth = (UINT32)TMEDIA_CONSUMER(pSelf)->video.in.width; + pSelf->nNegHeight = (UINT32)TMEDIA_CONSUMER(pSelf)->video.in.height; + + CHECK_HR(hr = CreateDeviceD3D9(hWnd, &pSelf->pDevice, &pSelf->pD3D, pSelf->d3dpp)); + CHECK_HR(hr = CreateSwapChain(hWnd, pSelf->nNegWidth, pSelf->nNegHeight, pSelf->pDevice, &pSelf->pSwapChain)); + } + } + + if(pSelf->nNegWidth != TMEDIA_CONSUMER(pSelf)->video.in.width || pSelf->nNegHeight != TMEDIA_CONSUMER(pSelf)->video.in.height) { + TSK_DEBUG_INFO("Negotiated and input video sizes are different:%d#%d or %d#%d", + pSelf->nNegWidth, TMEDIA_CONSUMER(pSelf)->video.in.width, + pSelf->nNegHeight, TMEDIA_CONSUMER(pSelf)->video.in.height); + // Update media type + + SafeRelease(&pSelf->pSwapChain); + CHECK_HR(hr = CreateSwapChain(hWnd, (UINT32)TMEDIA_CONSUMER(pSelf)->video.in.width, (UINT32)TMEDIA_CONSUMER(pSelf)->video.in.height, pSelf->pDevice, &pSelf->pSwapChain)); + + pSelf->nNegWidth = (UINT32)TMEDIA_CONSUMER(pSelf)->video.in.width; + pSelf->nNegHeight = (UINT32)TMEDIA_CONSUMER(pSelf)->video.in.height; + + // Update Destination will do noting if the window size haven't changed. + // Force updating the destination rect if negotiated size change + CHECK_HR(hr = UpdateDestinationRect(pSelf, TRUE/* Force */)); + } + + CHECK_HR(hr = TestCooperativeLevel(pSelf)); + + CHECK_HR(hr = UpdateDestinationRect(pSelf)); + + CHECK_HR(hr = pSelf->pSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pSurf)); + CHECK_HR(hr = pSurf->LockRect(&pSelf->rcLock, NULL, D3DLOCK_NOSYSLOCK )); + + // Fast copy() using MMX, SSE, or SSE2 + hr = MFCopyImage( + (BYTE*)pSelf->rcLock.pBits, + pSelf->rcLock.Pitch, + (BYTE*)buffer, + (pSelf->nNegWidth << 2), + (pSelf->nNegWidth << 2), + pSelf->nNegHeight + ); + if(FAILED(hr)) { + // unlock() before leaving + pSurf->UnlockRect(); + CHECK_HR(hr); + } + + CHECK_HR(hr = pSurf->UnlockRect()); + + // Color fill the back buffer + CHECK_HR(hr = pSelf->pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBB)); #if METROPOLIS - CHECK_HR(hr = pSelf->pDevice->ColorFill(pBB, NULL, D3DCOLOR_XRGB(0x00, 0x00, 0x00))); + CHECK_HR(hr = pSelf->pDevice->ColorFill(pBB, NULL, D3DCOLOR_XRGB(0x00, 0x00, 0x00))); #else - CHECK_HR(hr = pSelf->pDevice->ColorFill(pBB, NULL, D3DCOLOR_XRGB(0xFF, 0xFF, 0xFF))); + CHECK_HR(hr = pSelf->pDevice->ColorFill(pBB, NULL, D3DCOLOR_XRGB(0xFF, 0xFF, 0xFF))); #endif - - // Resize keeping aspect ratio and Blit the frame (required) - hr = pSelf->pDevice->StretchRect( - pSurf, - NULL, - pBB, - &pSelf->rcDest/*NULL*/, - D3DTEXF_LINEAR - ); // could fail when display is being resized - if(SUCCEEDED(hr)) - { - // Present the frame - CHECK_HR(hr = pSelf->pDevice->Present(NULL, NULL, NULL, NULL)); - } - else - { - TSK_DEBUG_INFO("StretchRect returned ...%x", hr); - } + + // Resize keeping aspect ratio and Blit the frame (required) + hr = pSelf->pDevice->StretchRect( + pSurf, + NULL, + pBB, + &pSelf->rcDest/*NULL*/, + D3DTEXF_LINEAR + ); // could fail when display is being resized + if(SUCCEEDED(hr)) { + // Present the frame + CHECK_HR(hr = pSelf->pDevice->Present(NULL, NULL, NULL, NULL)); + } + else { + TSK_DEBUG_INFO("StretchRect returned ...%x", hr); + } bail: - SafeRelease(&pSurf); - SafeRelease(&pBB); + SafeRelease(&pSurf); + SafeRelease(&pBB); - tsk_safeobj_unlock(pSelf); + tsk_safeobj_unlock(pSelf); - return SUCCEEDED(hr) ? 0 : -1; + return SUCCEEDED(hr) ? 0 : -1; } static int plugin_win_mf_consumer_video_pause(tmedia_consumer_t* self) { - plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; + plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; - if(!pSelf){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if(!pSelf->bStarted) - { - TSK_DEBUG_INFO("MF video producer not started"); - return 0; - } + if(!pSelf) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if(!pSelf->bStarted) { + TSK_DEBUG_INFO("MF video producer not started"); + return 0; + } - HRESULT hr = S_OK; + HRESULT hr = S_OK; - pSelf->bPaused = true; + pSelf->bPaused = true; - return SUCCEEDED(hr) ? 0 : -1; + return SUCCEEDED(hr) ? 0 : -1; } static int plugin_win_mf_consumer_video_stop(tmedia_consumer_t* self) { - plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; + plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; - if(!pSelf){ + if(!pSelf) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } - HRESULT hr = S_OK; - + HRESULT hr = S_OK; + pSelf->bStarted = false; - pSelf->bPaused = false; + pSelf->bPaused = false; - if(pSelf->hWindowFullScreen) - { - ::InvalidateRect(pSelf->hWindowFullScreen, NULL, FALSE); - ::ShowWindow(pSelf->hWindowFullScreen, SW_HIDE); - } + if(pSelf->hWindowFullScreen) { + ::InvalidateRect(pSelf->hWindowFullScreen, NULL, FALSE); + ::ShowWindow(pSelf->hWindowFullScreen, SW_HIDE); + } - // next start() will be called after prepare() - return _plugin_win_mf_consumer_video_unprepare(pSelf); + // next start() will be called after prepare() + return _plugin_win_mf_consumer_video_unprepare(pSelf); } static int _plugin_win_mf_consumer_video_unprepare(plugin_win_mf_consumer_video_t* pSelf) { - if(!pSelf) - { - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } + if(!pSelf) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } - UnhookWindow(pSelf); + UnhookWindow(pSelf); - if(pSelf->bStarted) - { - // plugin_win_mf_producer_video_stop(TMEDIA_PRODUCER(pSelf)); - TSK_DEBUG_ERROR("Consumer must be stopped before calling unprepare"); - return -1; - } + if(pSelf->bStarted) { + // plugin_win_mf_producer_video_stop(TMEDIA_PRODUCER(pSelf)); + TSK_DEBUG_ERROR("Consumer must be stopped before calling unprepare"); + return -1; + } - SafeRelease(&pSelf->pDevice); - SafeRelease(&pSelf->pD3D); - SafeRelease(&pSelf->pSwapChain); + SafeRelease(&pSelf->pDevice); + SafeRelease(&pSelf->pD3D); + SafeRelease(&pSelf->pSwapChain); - pSelf->bPrepared = false; + pSelf->bPrepared = false; - return 0; + return 0; } @@ -476,192 +446,179 @@ static int _plugin_win_mf_consumer_video_unprepare(plugin_win_mf_consumer_video_ /* constructor */ static tsk_object_t* plugin_win_mf_consumer_video_ctor(tsk_object_t * self, va_list * app) { - MFUtils::Startup(); - - plugin_win_mf_consumer_video_t *pSelf = (plugin_win_mf_consumer_video_t *)self; - if(pSelf){ - /* init base */ - tmedia_consumer_init(TMEDIA_CONSUMER(pSelf)); - TMEDIA_CONSUMER(pSelf)->video.display.chroma = tmedia_chroma_rgb32; - TMEDIA_CONSUMER(pSelf)->decoder.codec_id = tmedia_codec_id_none; // means accept RAW fames - - /* init self */ - tsk_safeobj_init(pSelf); - TMEDIA_CONSUMER(pSelf)->video.fps = 15; - TMEDIA_CONSUMER(pSelf)->video.display.width = 0; // use codec value - TMEDIA_CONSUMER(pSelf)->video.display.height = 0; // use codec value - TMEDIA_CONSUMER(pSelf)->video.display.auto_resize = tsk_true; - - pSelf->pixelAR.Denominator = pSelf->pixelAR.Numerator = 1; - } - return self; + MFUtils::Startup(); + + plugin_win_mf_consumer_video_t *pSelf = (plugin_win_mf_consumer_video_t *)self; + if(pSelf) { + /* init base */ + tmedia_consumer_init(TMEDIA_CONSUMER(pSelf)); + TMEDIA_CONSUMER(pSelf)->video.display.chroma = tmedia_chroma_rgb32; + TMEDIA_CONSUMER(pSelf)->decoder.codec_id = tmedia_codec_id_none; // means accept RAW fames + + /* init self */ + tsk_safeobj_init(pSelf); + TMEDIA_CONSUMER(pSelf)->video.fps = 15; + TMEDIA_CONSUMER(pSelf)->video.display.width = 0; // use codec value + TMEDIA_CONSUMER(pSelf)->video.display.height = 0; // use codec value + TMEDIA_CONSUMER(pSelf)->video.display.auto_resize = tsk_true; + + pSelf->pixelAR.Denominator = pSelf->pixelAR.Numerator = 1; + } + return self; } /* destructor */ static tsk_object_t* plugin_win_mf_consumer_video_dtor(tsk_object_t * self) -{ - plugin_win_mf_consumer_video_t *pSelf = (plugin_win_mf_consumer_video_t *)self; - if(pSelf){ - /* stop */ - if(pSelf->bStarted) - { - plugin_win_mf_consumer_video_stop(TMEDIA_CONSUMER(pSelf)); - } - - /* deinit base */ - tmedia_consumer_deinit(TMEDIA_CONSUMER(pSelf)); - /* deinit self */ - _plugin_win_mf_consumer_video_unprepare(pSelf); - tsk_safeobj_deinit(pSelf); - } - - return self; +{ + plugin_win_mf_consumer_video_t *pSelf = (plugin_win_mf_consumer_video_t *)self; + if(pSelf) { + /* stop */ + if(pSelf->bStarted) { + plugin_win_mf_consumer_video_stop(TMEDIA_CONSUMER(pSelf)); + } + + /* deinit base */ + tmedia_consumer_deinit(TMEDIA_CONSUMER(pSelf)); + /* deinit self */ + _plugin_win_mf_consumer_video_unprepare(pSelf); + tsk_safeobj_deinit(pSelf); + } + + return self; } /* object definition */ -static const tsk_object_def_t plugin_win_mf_consumer_video_def_s = -{ - sizeof(plugin_win_mf_consumer_video_t), - plugin_win_mf_consumer_video_ctor, - plugin_win_mf_consumer_video_dtor, - tsk_null, +static const tsk_object_def_t plugin_win_mf_consumer_video_def_s = { + sizeof(plugin_win_mf_consumer_video_t), + plugin_win_mf_consumer_video_ctor, + plugin_win_mf_consumer_video_dtor, + tsk_null, }; /* plugin definition*/ -static const tmedia_consumer_plugin_def_t plugin_win_mf_consumer_video_plugin_def_s = -{ - &plugin_win_mf_consumer_video_def_s, - - tmedia_video, - "D3D9 video consumer", - - plugin_win_mf_consumer_video_set, - plugin_win_mf_consumer_video_prepare, - plugin_win_mf_consumer_video_start, - plugin_win_mf_consumer_video_consume, - plugin_win_mf_consumer_video_pause, - plugin_win_mf_consumer_video_stop +static const tmedia_consumer_plugin_def_t plugin_win_mf_consumer_video_plugin_def_s = { + &plugin_win_mf_consumer_video_def_s, + + tmedia_video, + "D3D9 video consumer", + + plugin_win_mf_consumer_video_set, + plugin_win_mf_consumer_video_prepare, + plugin_win_mf_consumer_video_start, + plugin_win_mf_consumer_video_consume, + plugin_win_mf_consumer_video_pause, + plugin_win_mf_consumer_video_stop }; const tmedia_consumer_plugin_def_t *plugin_win_mf_consumer_video_plugin_def_t = &plugin_win_mf_consumer_video_plugin_def_s; // Helper functions static HRESULT CreateDeviceD3D9( - HWND hWnd, - IDirect3DDevice9** ppDevice, - IDirect3D9 **ppD3D, - D3DPRESENT_PARAMETERS &d3dpp - ) + HWND hWnd, + IDirect3DDevice9** ppDevice, + IDirect3D9 **ppD3D, + D3DPRESENT_PARAMETERS &d3dpp +) { - HRESULT hr = S_OK; + HRESULT hr = S_OK; D3DDISPLAYMODE mode = { 0 }; - D3DPRESENT_PARAMETERS pp = {0}; - - if(!ppDevice || *ppDevice || !ppD3D || *ppD3D) - { - CHECK_HR(hr = E_POINTER); - } - - if(!(*ppD3D = Direct3DCreate9(D3D_SDK_VERSION))) - { + D3DPRESENT_PARAMETERS pp = {0}; + + if(!ppDevice || *ppDevice || !ppD3D || *ppD3D) { + CHECK_HR(hr = E_POINTER); + } + + if(!(*ppD3D = Direct3DCreate9(D3D_SDK_VERSION))) { CHECK_HR(hr = E_OUTOFMEMORY); } CHECK_HR(hr = (*ppD3D)->GetAdapterDisplayMode( - D3DADAPTER_DEFAULT, - &mode - )); + D3DADAPTER_DEFAULT, + &mode + )); CHECK_HR(hr = (*ppD3D)->CheckDeviceType( - D3DADAPTER_DEFAULT, - D3DDEVTYPE_HAL, - mode.Format, - D3DFMT_X8R8G8B8, - TRUE // windowed - )); + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + mode.Format, + D3DFMT_X8R8G8B8, + TRUE // windowed + )); pp.BackBufferFormat = D3DFMT_X8R8G8B8; pp.SwapEffect = D3DSWAPEFFECT_DISCARD; pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; - pp.Windowed = TRUE; + pp.Windowed = TRUE; pp.hDeviceWindow = hWnd; CHECK_HR(hr = (*ppD3D)->CreateDevice( - D3DADAPTER_DEFAULT, - D3DDEVTYPE_HAL, - hWnd, - D3DCREATE_HARDWARE_VERTEXPROCESSING, - &pp, - ppDevice - )); + D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + hWnd, + D3DCREATE_HARDWARE_VERTEXPROCESSING, + &pp, + ppDevice + )); - d3dpp = pp; + d3dpp = pp; bail: - if(FAILED(hr)) - { - SafeRelease(ppD3D); - SafeRelease(ppDevice); - } + if(FAILED(hr)) { + SafeRelease(ppD3D); + SafeRelease(ppDevice); + } return hr; } static HRESULT TestCooperativeLevel( - struct plugin_win_mf_consumer_video_s *pSelf - ) + struct plugin_win_mf_consumer_video_s *pSelf +) { - HRESULT hr = S_OK; - - if (!pSelf || !pSelf->pDevice) - { - CHECK_HR(hr = E_POINTER); - } - - switch((hr = pSelf->pDevice->TestCooperativeLevel())) - { - case D3D_OK: - { - break; - } - - case D3DERR_DEVICELOST: - { - hr = S_OK; - break; - } - - case D3DERR_DEVICENOTRESET: - { - hr = ResetDevice(pSelf, TRUE); - break; - } - - default: - { - break; - } - } - - CHECK_HR(hr); + HRESULT hr = S_OK; + + if (!pSelf || !pSelf->pDevice) { + CHECK_HR(hr = E_POINTER); + } + + switch((hr = pSelf->pDevice->TestCooperativeLevel())) { + case D3D_OK: { + break; + } + + case D3DERR_DEVICELOST: { + hr = S_OK; + break; + } + + case D3DERR_DEVICENOTRESET: { + hr = ResetDevice(pSelf, TRUE); + break; + } + + default: { + break; + } + } + + CHECK_HR(hr); bail: return hr; } static HRESULT CreateSwapChain( - HWND hWnd, - UINT32 nFrameWidth, - UINT32 nFrameHeight, - IDirect3DDevice9* pDevice, - IDirect3DSwapChain9 **ppSwapChain - ) + HWND hWnd, + UINT32 nFrameWidth, + UINT32 nFrameHeight, + IDirect3DDevice9* pDevice, + IDirect3DSwapChain9 **ppSwapChain +) { HRESULT hr = S_OK; D3DPRESENT_PARAMETERS pp = { 0 }; - if(!pDevice || !ppSwapChain || *ppSwapChain) - { - CHECK_HR(hr = E_POINTER); - } - - pp.BackBufferWidth = nFrameWidth; + if(!pDevice || !ppSwapChain || *ppSwapChain) { + CHECK_HR(hr = E_POINTER); + } + + pp.BackBufferWidth = nFrameWidth; pp.BackBufferHeight = nFrameHeight; pp.Windowed = TRUE; pp.SwapEffect = D3DSWAPEFFECT_FLIP; @@ -673,7 +630,7 @@ static HRESULT CreateSwapChain( pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; pp.BackBufferCount = NUM_BACK_BUFFERS; - CHECK_HR(hr = pDevice->CreateAdditionalSwapChain(&pp, ppSwapChain)); + CHECK_HR(hr = pDevice->CreateAdditionalSwapChain(&pp, ppSwapChain)); bail: return hr; @@ -681,7 +638,7 @@ bail: static inline HWND Window(struct plugin_win_mf_consumer_video_s *pSelf) { - return pSelf ? (pSelf->bFullScreen ? pSelf->hWindowFullScreen : pSelf->hWindow) : NULL; + return pSelf ? (pSelf->bFullScreen ? pSelf->hWindowFullScreen : pSelf->hWindow) : NULL; } static inline LONG Width(const RECT& r) @@ -710,17 +667,14 @@ static inline RECT CorrectAspectRatio(const RECT& src, const MFRatio& srcPAR) // Start with a rectangle the same size as src, but offset to the origin (0,0). RECT rc = {0, 0, src.right - src.left, src.bottom - src.top}; - if ((srcPAR.Numerator != 1) || (srcPAR.Denominator != 1)) - { + if ((srcPAR.Numerator != 1) || (srcPAR.Denominator != 1)) { // Correct for the source's PAR. - if (srcPAR.Numerator > srcPAR.Denominator) - { + if (srcPAR.Numerator > srcPAR.Denominator) { // The source has "wide" pixels, so stretch the width. rc.right = MulDiv(rc.right, srcPAR.Numerator, srcPAR.Denominator); } - else if (srcPAR.Numerator < srcPAR.Denominator) - { + else if (srcPAR.Numerator < srcPAR.Denominator) { // The source has "tall" pixels, so stretch the height. rc.bottom = MulDiv(rc.bottom, srcPAR.Denominator, srcPAR.Numerator); } @@ -783,236 +737,214 @@ static inline RECT LetterBoxRect(const RECT& rcSrc, const RECT& rcDst) static inline HRESULT UpdateDestinationRect(plugin_win_mf_consumer_video_t *pSelf, BOOL bForce /*= FALSE*/) { - HRESULT hr = S_OK; - HWND hwnd = Window(pSelf); - - if(!pSelf) - { - CHECK_HR(hr = E_POINTER); - } - - if(!hwnd) - { - CHECK_HR(hr = E_HANDLE); - } + HRESULT hr = S_OK; + HWND hwnd = Window(pSelf); + + if(!pSelf) { + CHECK_HR(hr = E_POINTER); + } + + if(!hwnd) { + CHECK_HR(hr = E_HANDLE); + } RECT rcClient; - GetClientRect(hwnd, &rcClient); + GetClientRect(hwnd, &rcClient); - // only update destination if window size changed - if(bForce || (rcClient.bottom != pSelf->rcWindow.bottom || rcClient.left != pSelf->rcWindow.left || rcClient.right != pSelf->rcWindow.right || rcClient.top != pSelf->rcWindow.top)) - { - CHECK_HR(hr = ResetDevice(pSelf)); + // only update destination if window size changed + if(bForce || (rcClient.bottom != pSelf->rcWindow.bottom || rcClient.left != pSelf->rcWindow.left || rcClient.right != pSelf->rcWindow.right || rcClient.top != pSelf->rcWindow.top)) { + CHECK_HR(hr = ResetDevice(pSelf)); - pSelf->rcWindow = rcClient; + pSelf->rcWindow = rcClient; #if 1 - RECT rcSrc = { 0, 0, pSelf->nNegWidth, pSelf->nNegHeight }; - rcSrc = CorrectAspectRatio(rcSrc, pSelf->pixelAR); - pSelf->rcDest = LetterBoxRect(rcSrc, rcClient); + RECT rcSrc = { 0, 0, pSelf->nNegWidth, pSelf->nNegHeight }; + rcSrc = CorrectAspectRatio(rcSrc, pSelf->pixelAR); + pSelf->rcDest = LetterBoxRect(rcSrc, rcClient); #else - long w = rcClient.right - rcClient.left; - long h = rcClient.bottom - rcClient.top; - float ratio = ((float)pSelf->nNegWidth/(float)pSelf->nNegHeight); - // (w/h)=ratio => - // 1) h=w/ratio - // and - // 2) w=h*ratio - pSelf->rcDest.right = (int)(w/ratio) > h ? (int)(h * ratio) : w; - pSelf->rcDest.bottom = (int)(pSelf->rcDest.right/ratio) > h ? h : (int)(pSelf->rcDest.right/ratio); - pSelf->rcDest.left = ((w - pSelf->rcDest.right) >> 1); - pSelf->rcDest.top = ((h - pSelf->rcDest.bottom) >> 1); + long w = rcClient.right - rcClient.left; + long h = rcClient.bottom - rcClient.top; + float ratio = ((float)pSelf->nNegWidth/(float)pSelf->nNegHeight); + // (w/h)=ratio => + // 1) h=w/ratio + // and + // 2) w=h*ratio + pSelf->rcDest.right = (int)(w/ratio) > h ? (int)(h * ratio) : w; + pSelf->rcDest.bottom = (int)(pSelf->rcDest.right/ratio) > h ? h : (int)(pSelf->rcDest.right/ratio); + pSelf->rcDest.left = ((w - pSelf->rcDest.right) >> 1); + pSelf->rcDest.top = ((h - pSelf->rcDest.bottom) >> 1); #endif - //::InvalidateRect(hwnd, NULL, FALSE); - } + //::InvalidateRect(hwnd, NULL, FALSE); + } bail: - return hr; + return hr; } static HRESULT ResetDevice(plugin_win_mf_consumer_video_t *pSelf, BOOL bUpdateDestinationRect /*= FALSE*/) { HRESULT hr = S_OK; - tsk_safeobj_lock(pSelf); + tsk_safeobj_lock(pSelf); - HWND hWnd = Window(pSelf); + HWND hWnd = Window(pSelf); - if (pSelf->pDevice) - { + if (pSelf->pDevice) { D3DPRESENT_PARAMETERS d3dpp = pSelf->d3dpp; hr = pSelf->pDevice->Reset(&d3dpp); - if (FAILED(hr)) - { + if (FAILED(hr)) { SafeRelease(&pSelf->pDevice); - SafeRelease(&pSelf->pD3D); - SafeRelease(&pSelf->pSwapChain); + SafeRelease(&pSelf->pD3D); + SafeRelease(&pSelf->pSwapChain); } } - if (pSelf->pDevice == NULL && hWnd) - { + if (pSelf->pDevice == NULL && hWnd) { CHECK_HR(hr = CreateDeviceD3D9(hWnd, &pSelf->pDevice, &pSelf->pD3D, pSelf->d3dpp)); - CHECK_HR(hr = CreateSwapChain(hWnd, pSelf->nNegWidth, pSelf->nNegHeight, pSelf->pDevice, &pSelf->pSwapChain)); - } + CHECK_HR(hr = CreateSwapChain(hWnd, pSelf->nNegWidth, pSelf->nNegHeight, pSelf->pDevice, &pSelf->pSwapChain)); + } - if(bUpdateDestinationRect) // endless loop guard - { - CHECK_HR(hr = UpdateDestinationRect(pSelf)); - } + if(bUpdateDestinationRect) { // endless loop guard + CHECK_HR(hr = UpdateDestinationRect(pSelf)); + } bail: - tsk_safeobj_unlock(pSelf); + tsk_safeobj_unlock(pSelf); - return hr; + return hr; } static HRESULT SetFullscreen(struct plugin_win_mf_consumer_video_s *pSelf, BOOL bFullScreen) { - HRESULT hr = S_OK; - if(!pSelf) - { - CHECK_HR(hr = E_POINTER); - } - - if(pSelf->bFullScreen != bFullScreen) - { - tsk_safeobj_lock(pSelf); - if(bFullScreen) - { - HWND hWnd = CreateFullScreenWindow(pSelf); - if(hWnd) - { - ::ShowWindow(hWnd, SW_SHOWDEFAULT); - ::UpdateWindow(hWnd); - } - } - else if(pSelf->hWindowFullScreen) - { - ::ShowWindow(pSelf->hWindowFullScreen, SW_HIDE); - } - pSelf->bFullScreen = bFullScreen; - if(pSelf->bPrepared) - { - hr = ResetDevice(pSelf); - } - tsk_safeobj_unlock(pSelf); - - CHECK_HR(hr); - } + HRESULT hr = S_OK; + if(!pSelf) { + CHECK_HR(hr = E_POINTER); + } + + if(pSelf->bFullScreen != bFullScreen) { + tsk_safeobj_lock(pSelf); + if(bFullScreen) { + HWND hWnd = CreateFullScreenWindow(pSelf); + if(hWnd) { + ::ShowWindow(hWnd, SW_SHOWDEFAULT); + ::UpdateWindow(hWnd); + } + } + else if(pSelf->hWindowFullScreen) { + ::ShowWindow(pSelf->hWindowFullScreen, SW_HIDE); + } + pSelf->bFullScreen = bFullScreen; + if(pSelf->bPrepared) { + hr = ResetDevice(pSelf); + } + tsk_safeobj_unlock(pSelf); + + CHECK_HR(hr); + } bail: - return hr; + return hr; } static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - switch(uMsg) - { - case WM_CREATE: - case WM_SIZE: - case WM_MOVE: - { - struct plugin_win_mf_consumer_video_s* pSelf = dynamic_cast<struct plugin_win_mf_consumer_video_s*>((struct plugin_win_mf_consumer_video_s*)GetPropA(hWnd, "Self")); - if (pSelf) - { - - } - break; - } - - case WM_ERASEBKGND: - { - return TRUE; // avoid background erasing. - } - - case WM_CHAR: - case WM_KEYUP: - { - struct plugin_win_mf_consumer_video_s* pSelf = dynamic_cast<struct plugin_win_mf_consumer_video_s*>((struct plugin_win_mf_consumer_video_s*)GetPropA(hWnd, "Self")); - if (pSelf) - { - SetFullscreen(pSelf, FALSE); - } - - break; - } - } - - return DefWindowProc(hWnd, uMsg, wParam, lParam); + switch(uMsg) { + case WM_CREATE: + case WM_SIZE: + case WM_MOVE: { + struct plugin_win_mf_consumer_video_s* pSelf = dynamic_cast<struct plugin_win_mf_consumer_video_s*>((struct plugin_win_mf_consumer_video_s*)GetPropA(hWnd, "Self")); + if (pSelf) { + + } + break; + } + + case WM_ERASEBKGND: { + return TRUE; // avoid background erasing. + } + + case WM_CHAR: + case WM_KEYUP: { + struct plugin_win_mf_consumer_video_s* pSelf = dynamic_cast<struct plugin_win_mf_consumer_video_s*>((struct plugin_win_mf_consumer_video_s*)GetPropA(hWnd, "Self")); + if (pSelf) { + SetFullscreen(pSelf, FALSE); + } + + break; + } + } + + return DefWindowProc(hWnd, uMsg, wParam, lParam); } static HWND CreateFullScreenWindow(struct plugin_win_mf_consumer_video_s *pSelf) { - HRESULT hr = S_OK; - - if(!pSelf) - { - return NULL; - } - - if(!pSelf->hWindowFullScreen) - { - WNDCLASS wc = {0}; - - wc.lpfnWndProc = WndProc; - wc.hInstance = GetModuleHandle(NULL); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.lpszClassName = L"WindowClass"; - RegisterClass(&wc); - pSelf->hWindowFullScreen = ::CreateWindowEx( - NULL, - wc.lpszClassName, - L"Doubango's Video Consumer Fullscreen", - WS_EX_TOPMOST | WS_POPUP, - 0, 0, - GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), - NULL, - NULL, - GetModuleHandle(NULL), - NULL); - - SetPropA(pSelf->hWindowFullScreen, "Self", pSelf); - } - return pSelf->hWindowFullScreen; + HRESULT hr = S_OK; + + if(!pSelf) { + return NULL; + } + + if(!pSelf->hWindowFullScreen) { + WNDCLASS wc = {0}; + + wc.lpfnWndProc = WndProc; + wc.hInstance = GetModuleHandle(NULL); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.lpszClassName = L"WindowClass"; + RegisterClass(&wc); + pSelf->hWindowFullScreen = ::CreateWindowEx( + NULL, + wc.lpszClassName, + L"Doubango's Video Consumer Fullscreen", + WS_EX_TOPMOST | WS_POPUP, + 0, 0, + GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), + NULL, + NULL, + GetModuleHandle(NULL), + NULL); + + SetPropA(pSelf->hWindowFullScreen, "Self", pSelf); + } + return pSelf->hWindowFullScreen; } static HRESULT HookWindow(plugin_win_mf_consumer_video_s *pSelf, HWND hWnd) { - HRESULT hr = S_OK; + HRESULT hr = S_OK; - tsk_safeobj_lock(pSelf); + tsk_safeobj_lock(pSelf); - CHECK_HR(hr = UnhookWindow(pSelf)); + CHECK_HR(hr = UnhookWindow(pSelf)); - if ((pSelf->hWindow = hWnd)) { - pSelf->wndProc = (WNDPROC)SetWindowLongPtr(pSelf->hWindow, GWLP_WNDPROC, (LONG_PTR)WndProc); - if (!pSelf->wndProc) { - TSK_DEBUG_ERROR("HookWindowLongPtr() failed with errcode=%d", GetLastError()); - CHECK_HR(hr = E_FAIL); - } - pSelf->bWindowHooked = TRUE; - } + if ((pSelf->hWindow = hWnd)) { + pSelf->wndProc = (WNDPROC)SetWindowLongPtr(pSelf->hWindow, GWLP_WNDPROC, (LONG_PTR)WndProc); + if (!pSelf->wndProc) { + TSK_DEBUG_ERROR("HookWindowLongPtr() failed with errcode=%d", GetLastError()); + CHECK_HR(hr = E_FAIL); + } + pSelf->bWindowHooked = TRUE; + } bail: - tsk_safeobj_unlock(pSelf); - return S_OK; + tsk_safeobj_unlock(pSelf); + return S_OK; } static HRESULT UnhookWindow(struct plugin_win_mf_consumer_video_s *pSelf) { - tsk_safeobj_lock(pSelf); - if (pSelf->hWindow && pSelf->wndProc) { - SetWindowLongPtr(pSelf->hWindow, GWLP_WNDPROC, (LONG_PTR)pSelf->wndProc); - pSelf->wndProc = NULL; - } - if(pSelf->hWindow) - { - ::InvalidateRect(pSelf->hWindow, NULL, FALSE); - } - pSelf->bWindowHooked = FALSE; - tsk_safeobj_unlock(pSelf); - return S_OK; + tsk_safeobj_lock(pSelf); + if (pSelf->hWindow && pSelf->wndProc) { + SetWindowLongPtr(pSelf->hWindow, GWLP_WNDPROC, (LONG_PTR)pSelf->wndProc); + pSelf->wndProc = NULL; + } + if(pSelf->hWindow) { + ::InvalidateRect(pSelf->hWindow, NULL, FALSE); + } + pSelf->bWindowHooked = FALSE; + tsk_safeobj_unlock(pSelf); + return S_OK; } @@ -1038,39 +970,38 @@ static HRESULT UnhookWindow(struct plugin_win_mf_consumer_video_s *pSelf) // To avoid chroma conversion (performance issues) we use NV12 when the codec is bundled as MediaFoundation codecs most likely only support this format. // NV12 is the native format for media foundation codecs (e.g. Intel Quick Sync) and the GPU. // I420 is the native format for FFmpeg, libvpx and libtheora. -const GUID kDefaultUncompressedType +const GUID kDefaultUncompressedType #if PLUGIN_MF_CV_BUNDLE_CODEC -= MFVideoFormat_NV12; + = MFVideoFormat_NV12; #else -= MFVideoFormat_I420; + = MFVideoFormat_I420; #endif DEFINE_GUID(PLUGIN_MF_LOW_LATENCY, -0x9c27891a, 0xed7a, 0x40e1, 0x88, 0xe8, 0xb2, 0x27, 0x27, 0xa0, 0x24, 0xee); + 0x9c27891a, 0xed7a, 0x40e1, 0x88, 0xe8, 0xb2, 0x27, 0x27, 0xa0, 0x24, 0xee); static void* TSK_STDCALL RunSessionThread(void *pArg); static int _plugin_win_mf_consumer_video_unprepare(struct plugin_win_mf_consumer_video_s* pSelf); -typedef struct plugin_win_mf_consumer_video_s -{ - TMEDIA_DECLARE_CONSUMER; - - bool bStarted, bPrepared; - HWND hWindow; - tsk_thread_handle_t* ppTread[1]; +typedef struct plugin_win_mf_consumer_video_s { + TMEDIA_DECLARE_CONSUMER; + + bool bStarted, bPrepared; + HWND hWindow; + tsk_thread_handle_t* ppTread[1]; - UINT32 nNegWidth; - UINT32 nNegHeight; - UINT32 nNegFps; + UINT32 nNegWidth; + UINT32 nNegHeight; + UINT32 nNegFps; - MFCodecVideo *pDecoder; + MFCodecVideo *pDecoder; IMFMediaSession *pSession; CMFSource *pSource; IMFActivate *pSinkActivate; - DisplayWatcher* pDisplayWatcher; + DisplayWatcher* pDisplayWatcher; IMFTopology *pTopologyFull; - IMFTopology *pTopologyPartial; - IMFMediaType *pOutType; + IMFTopology *pTopologyPartial; + IMFMediaType *pOutType; } plugin_win_mf_consumer_video_t; @@ -1079,437 +1010,437 @@ plugin_win_mf_consumer_video_t; /* ============ Media Consumer Interface ================= */ static int plugin_win_mf_consumer_video_set(tmedia_consumer_t *self, const tmedia_param_t* param) { - int ret = 0; - HRESULT hr = S_OK; - plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; - - if(!self || !param){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if(param->value_type == tmedia_pvt_int64){ - if(tsk_striequals(param->key, "remote-hwnd")){ - HWND hWnd = reinterpret_cast<HWND>((INT64)*((int64_t*)param->value)); - if(hWnd != pSelf->hWindow) - { - pSelf->hWindow = hWnd; - if(pSelf->pDisplayWatcher) - { - CHECK_HR(hr = pSelf->pDisplayWatcher->SetHwnd(hWnd)); - } - } - } - } - else if(param->value_type == tmedia_pvt_int32){ - if(tsk_striequals(param->key, "fullscreen")){ - if(pSelf->pDisplayWatcher) - { - CHECK_HR(hr = pSelf->pDisplayWatcher->SetFullscreen(!!*((int32_t*)param->value))); - } - } - else if(tsk_striequals(param->key, "create-on-current-thead")){ - // DSCONSUMER(self)->create_on_ui_thread = *((int32_t*)param->value) ? tsk_false : tsk_true; - } - else if(tsk_striequals(param->key, "plugin-firefox")){ - /*DSCONSUMER(self)->plugin_firefox = (*((int32_t*)param->value) != 0); - if(DSCONSUMER(self)->display){ - DSCONSUMER(self)->display->setPluginFirefox((DSCONSUMER(self)->plugin_firefox == tsk_true)); - }*/ - } - } + int ret = 0; + HRESULT hr = S_OK; + plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; + + if(!self || !param) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if(param->value_type == tmedia_pvt_int64) { + if(tsk_striequals(param->key, "remote-hwnd")) { + HWND hWnd = reinterpret_cast<HWND>((INT64)*((int64_t*)param->value)); + if(hWnd != pSelf->hWindow) { + pSelf->hWindow = hWnd; + if(pSelf->pDisplayWatcher) { + CHECK_HR(hr = pSelf->pDisplayWatcher->SetHwnd(hWnd)); + } + } + } + } + else if(param->value_type == tmedia_pvt_int32) { + if(tsk_striequals(param->key, "fullscreen")) { + if(pSelf->pDisplayWatcher) { + CHECK_HR(hr = pSelf->pDisplayWatcher->SetFullscreen(!!*((int32_t*)param->value))); + } + } + else if(tsk_striequals(param->key, "create-on-current-thead")) { + // DSCONSUMER(self)->create_on_ui_thread = *((int32_t*)param->value) ? tsk_false : tsk_true; + } + else if(tsk_striequals(param->key, "plugin-firefox")) { + /*DSCONSUMER(self)->plugin_firefox = (*((int32_t*)param->value) != 0); + if(DSCONSUMER(self)->display){ + DSCONSUMER(self)->display->setPluginFirefox((DSCONSUMER(self)->plugin_firefox == tsk_true)); + }*/ + } + } bail: - return SUCCEEDED(hr) ? 0 : -1; + return SUCCEEDED(hr) ? 0 : -1; } static int plugin_win_mf_consumer_video_prepare(tmedia_consumer_t* self, const tmedia_codec_t* codec) { - plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; - - if(!pSelf || !codec && codec->plugin){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if(pSelf->bPrepared){ - TSK_DEBUG_WARN("MF video consumer already prepared"); - return -1; - } - - // FIXME: DirectShow requires flipping but not MF - // The Core library always tries to flip when OSType==Win32. Must be changed - TMEDIA_CODEC_VIDEO(codec)->in.flip = tsk_false; - - HRESULT hr = S_OK; - - TMEDIA_CONSUMER(pSelf)->video.fps = TMEDIA_CODEC_VIDEO(codec)->in.fps; - TMEDIA_CONSUMER(pSelf)->video.in.width = TMEDIA_CODEC_VIDEO(codec)->in.width; - TMEDIA_CONSUMER(pSelf)->video.in.height = TMEDIA_CODEC_VIDEO(codec)->in.height; - - if(!TMEDIA_CONSUMER(pSelf)->video.display.width){ - TMEDIA_CONSUMER(pSelf)->video.display.width = TMEDIA_CONSUMER(pSelf)->video.in.width; - } - if(!TMEDIA_CONSUMER(pSelf)->video.display.height){ - TMEDIA_CONSUMER(pSelf)->video.display.height = TMEDIA_CONSUMER(pSelf)->video.in.height; - } - - pSelf->nNegFps = TMEDIA_CONSUMER(pSelf)->video.fps; - pSelf->nNegWidth = TMEDIA_CONSUMER(pSelf)->video.display.width; - pSelf->nNegHeight = TMEDIA_CONSUMER(pSelf)->video.display.height; - - TSK_DEBUG_INFO("MF video consumer: fps=%d, width=%d, height=%d", - pSelf->nNegFps, - pSelf->nNegWidth, - pSelf->nNegHeight); - - if(kDefaultUncompressedType == MFVideoFormat_NV12) { - TMEDIA_CONSUMER(pSelf)->video.display.chroma = tmedia_chroma_nv12; - } - else if(kDefaultUncompressedType == MFVideoFormat_I420) { - TMEDIA_CONSUMER(pSelf)->video.display.chroma = tmedia_chroma_yuv420p; - } - else if(kDefaultUncompressedType == MFVideoFormat_RGB32) { - TMEDIA_CONSUMER(pSelf)->video.display.chroma = tmedia_chroma_rgb32; - } - else if(kDefaultUncompressedType == MFVideoFormat_RGB24) { - TMEDIA_CONSUMER(pSelf)->video.display.chroma = tmedia_chroma_rgb24; - } - else { - CHECK_HR(hr = E_NOTIMPL); - } - TMEDIA_CONSUMER(pSelf)->decoder.codec_id = tmedia_codec_id_none; // means accept RAW fames - - IMFMediaSink* pMediaSink = NULL; - IMFAttributes* pSessionAttributes = NULL; - - // Set session attributes - CHECK_HR(hr = MFCreateAttributes(&pSessionAttributes, 1)); - CHECK_HR(hr = pSessionAttributes->SetUINT32(PLUGIN_MF_LOW_LATENCY, 1)); - - CHECK_HR(hr = MFCreateMediaType(&pSelf->pOutType)); - CHECK_HR(hr = pSelf->pOutType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video)); + plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; + + if(!pSelf || !codec && codec->plugin) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if(pSelf->bPrepared) { + TSK_DEBUG_WARN("MF video consumer already prepared"); + return -1; + } + + // FIXME: DirectShow requires flipping but not MF + // The Core library always tries to flip when OSType==Win32. Must be changed + TMEDIA_CODEC_VIDEO(codec)->in.flip = tsk_false; + + HRESULT hr = S_OK; + + TMEDIA_CONSUMER(pSelf)->video.fps = TMEDIA_CODEC_VIDEO(codec)->in.fps; + TMEDIA_CONSUMER(pSelf)->video.in.width = TMEDIA_CODEC_VIDEO(codec)->in.width; + TMEDIA_CONSUMER(pSelf)->video.in.height = TMEDIA_CODEC_VIDEO(codec)->in.height; + + if(!TMEDIA_CONSUMER(pSelf)->video.display.width) { + TMEDIA_CONSUMER(pSelf)->video.display.width = TMEDIA_CONSUMER(pSelf)->video.in.width; + } + if(!TMEDIA_CONSUMER(pSelf)->video.display.height) { + TMEDIA_CONSUMER(pSelf)->video.display.height = TMEDIA_CONSUMER(pSelf)->video.in.height; + } + + pSelf->nNegFps = TMEDIA_CONSUMER(pSelf)->video.fps; + pSelf->nNegWidth = TMEDIA_CONSUMER(pSelf)->video.display.width; + pSelf->nNegHeight = TMEDIA_CONSUMER(pSelf)->video.display.height; + + TSK_DEBUG_INFO("MF video consumer: fps=%d, width=%d, height=%d", + pSelf->nNegFps, + pSelf->nNegWidth, + pSelf->nNegHeight); + + if(kDefaultUncompressedType == MFVideoFormat_NV12) { + TMEDIA_CONSUMER(pSelf)->video.display.chroma = tmedia_chroma_nv12; + } + else if(kDefaultUncompressedType == MFVideoFormat_I420) { + TMEDIA_CONSUMER(pSelf)->video.display.chroma = tmedia_chroma_yuv420p; + } + else if(kDefaultUncompressedType == MFVideoFormat_RGB32) { + TMEDIA_CONSUMER(pSelf)->video.display.chroma = tmedia_chroma_rgb32; + } + else if(kDefaultUncompressedType == MFVideoFormat_RGB24) { + TMEDIA_CONSUMER(pSelf)->video.display.chroma = tmedia_chroma_rgb24; + } + else { + CHECK_HR(hr = E_NOTIMPL); + } + TMEDIA_CONSUMER(pSelf)->decoder.codec_id = tmedia_codec_id_none; // means accept RAW fames + + IMFMediaSink* pMediaSink = NULL; + IMFAttributes* pSessionAttributes = NULL; + + // Set session attributes + CHECK_HR(hr = MFCreateAttributes(&pSessionAttributes, 1)); + CHECK_HR(hr = pSessionAttributes->SetUINT32(PLUGIN_MF_LOW_LATENCY, 1)); + + CHECK_HR(hr = MFCreateMediaType(&pSelf->pOutType)); + CHECK_HR(hr = pSelf->pOutType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video)); #if PLUGIN_MF_CV_BUNDLE_CODEC - if((codec->id == tmedia_codec_id_h264_bp || codec->id == tmedia_codec_id_h264_mp) && MFUtils::IsLowLatencyH264Supported()) { - // both Microsoft and Intel encoders support NV12 only as input - // static const BOOL kIsEncoder = FALSE; - // hr = MFUtils::GetBestCodec(kIsEncoder, MFMediaType_Video, MFVideoFormat_H264, MFVideoFormat_NV12, &pSelf->pDecoder); - pSelf->pDecoder = (codec->id == tmedia_codec_id_h264_bp) ? MFCodecVideoH264::CreateCodecH264Base(MFCodecType_Decoder) : MFCodecVideoH264::CreateCodecH264Main(MFCodecType_Decoder); - if(pSelf->pDecoder) - { - hr = pSelf->pDecoder->Initialize( - pSelf->nNegFps, - pSelf->nNegWidth, - pSelf->nNegHeight); - - if(FAILED(hr)) - { - SafeRelease(&pSelf->pDecoder); - hr = S_OK; - } - } - if(SUCCEEDED(hr) && pSelf->pDecoder) { - TMEDIA_CONSUMER(pSelf)->decoder.codec_id = codec->id; // means accept ENCODED fames - CHECK_HR(hr = pSelf->pOutType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264)); - } - else { - SafeRelease(&pSelf->pDecoder); - TSK_DEBUG_WARN("Failed to find H.264 HW encoder...fallback to SW implementation"); - } - } + if((codec->id == tmedia_codec_id_h264_bp || codec->id == tmedia_codec_id_h264_mp) && MFUtils::IsLowLatencyH264Supported()) { + // both Microsoft and Intel encoders support NV12 only as input + // static const BOOL kIsEncoder = FALSE; + // hr = MFUtils::GetBestCodec(kIsEncoder, MFMediaType_Video, MFVideoFormat_H264, MFVideoFormat_NV12, &pSelf->pDecoder); + pSelf->pDecoder = (codec->id == tmedia_codec_id_h264_bp) ? MFCodecVideoH264::CreateCodecH264Base(MFCodecType_Decoder) : MFCodecVideoH264::CreateCodecH264Main(MFCodecType_Decoder); + if(pSelf->pDecoder) { + hr = pSelf->pDecoder->Initialize( + pSelf->nNegFps, + pSelf->nNegWidth, + pSelf->nNegHeight); + + if(FAILED(hr)) { + SafeRelease(&pSelf->pDecoder); + hr = S_OK; + } + } + if(SUCCEEDED(hr) && pSelf->pDecoder) { + TMEDIA_CONSUMER(pSelf)->decoder.codec_id = codec->id; // means accept ENCODED fames + CHECK_HR(hr = pSelf->pOutType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264)); + } + else { + SafeRelease(&pSelf->pDecoder); + TSK_DEBUG_WARN("Failed to find H.264 HW encoder...fallback to SW implementation"); + } + } #endif - if(!pSelf->pDecoder){ - CHECK_HR(hr = pSelf->pOutType->SetGUID(MF_MT_SUBTYPE, kDefaultUncompressedType)); - TMEDIA_CONSUMER(pSelf)->video.display.chroma = kDefaultUncompressedType == MFVideoFormat_NV12 ? tmedia_chroma_nv12 : tmedia_chroma_yuv420p; - } + if(!pSelf->pDecoder) { + CHECK_HR(hr = pSelf->pOutType->SetGUID(MF_MT_SUBTYPE, kDefaultUncompressedType)); + TMEDIA_CONSUMER(pSelf)->video.display.chroma = kDefaultUncompressedType == MFVideoFormat_NV12 ? tmedia_chroma_nv12 : tmedia_chroma_yuv420p; + } CHECK_HR(hr = pSelf->pOutType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive)); - CHECK_HR(hr = pSelf->pOutType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE)); + CHECK_HR(hr = pSelf->pOutType->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, TRUE)); CHECK_HR(hr = MFSetAttributeSize(pSelf->pOutType, MF_MT_FRAME_SIZE, pSelf->nNegWidth, pSelf->nNegHeight)); - CHECK_HR(hr = MFSetAttributeRatio(pSelf->pOutType, MF_MT_FRAME_RATE, pSelf->nNegFps, 1)); + CHECK_HR(hr = MFSetAttributeRatio(pSelf->pOutType, MF_MT_FRAME_RATE, pSelf->nNegFps, 1)); CHECK_HR(hr = MFSetAttributeRatio(pSelf->pOutType, MF_MT_PIXEL_ASPECT_RATIO, 1, 1)); - CHECK_HR(hr = CMFSource::CreateInstanceEx(IID_IMFMediaSource, (void**)&pSelf->pSource, pSelf->pOutType)); + CHECK_HR(hr = CMFSource::CreateInstanceEx(IID_IMFMediaSource, (void**)&pSelf->pSource, pSelf->pOutType)); - // Apply Encoder output type (must be called before SetInputType) - //if(pSelf->pDecoder) { - // CHECK_HR(hr = pSelf->pDecoder->SetOutputType(0, pSelf->pOutType, 0/*MFT_SET_TYPE_TEST_ONLY*/)); - //} + // Apply Encoder output type (must be called before SetInputType) + //if(pSelf->pDecoder) { + // CHECK_HR(hr = pSelf->pDecoder->SetOutputType(0, pSelf->pOutType, 0/*MFT_SET_TYPE_TEST_ONLY*/)); + //} - // Create the Media Session. - CHECK_HR(hr = MFCreateMediaSession(pSessionAttributes, &pSelf->pSession)); + // Create the Media Session. + CHECK_HR(hr = MFCreateMediaSession(pSessionAttributes, &pSelf->pSession)); - // Create the EVR activation object. - CHECK_HR(hr = MFCreateVideoRendererActivate(pSelf->hWindow, &pSelf->pSinkActivate)); + // Create the EVR activation object. + CHECK_HR(hr = MFCreateVideoRendererActivate(pSelf->hWindow, &pSelf->pSinkActivate)); - // Create the topology. - CHECK_HR(hr = MFUtils::CreateTopology( - pSelf->pSource, - pSelf->pDecoder ? pSelf->pDecoder->GetMFT() : NULL, - pSelf->pSinkActivate, - NULL/*Preview*/, - pSelf->pOutType, - &pSelf->pTopologyPartial)); - // Resolve topology (adds video processors if needed). - CHECK_HR(hr = MFUtils::ResolveTopology(pSelf->pTopologyPartial, &pSelf->pTopologyFull)); + // Create the topology. + CHECK_HR(hr = MFUtils::CreateTopology( + pSelf->pSource, + pSelf->pDecoder ? pSelf->pDecoder->GetMFT() : NULL, + pSelf->pSinkActivate, + NULL/*Preview*/, + pSelf->pOutType, + &pSelf->pTopologyPartial)); + // Resolve topology (adds video processors if needed). + CHECK_HR(hr = MFUtils::ResolveTopology(pSelf->pTopologyPartial, &pSelf->pTopologyFull)); - // Find EVR - CHECK_HR(hr = MFUtils::FindNodeObject(pSelf->pTopologyFull, MFUtils::g_ullTopoIdSinkMain, (void**)&pMediaSink)); + // Find EVR + CHECK_HR(hr = MFUtils::FindNodeObject(pSelf->pTopologyFull, MFUtils::g_ullTopoIdSinkMain, (void**)&pMediaSink)); - // Create EVR watcher - pSelf->pDisplayWatcher = new DisplayWatcher(pSelf->hWindow, pMediaSink, hr); - CHECK_HR(hr); + // Create EVR watcher + pSelf->pDisplayWatcher = new DisplayWatcher(pSelf->hWindow, pMediaSink, hr); + CHECK_HR(hr); bail: - SafeRelease(&pMediaSink); - SafeRelease(&pSessionAttributes); - - pSelf->bPrepared = SUCCEEDED(hr); - return pSelf->bPrepared ? 0 : -1; + SafeRelease(&pMediaSink); + SafeRelease(&pSessionAttributes); + + pSelf->bPrepared = SUCCEEDED(hr); + return pSelf->bPrepared ? 0 : -1; } static int plugin_win_mf_consumer_video_start(tmedia_consumer_t* self) { - plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; - - if(!pSelf){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if(pSelf->bStarted){ - TSK_DEBUG_INFO("MF video consumer already started"); - return 0; - } - if(!pSelf->bPrepared){ - TSK_DEBUG_ERROR("MF video consumer not prepared"); - return -1; - } - - HRESULT hr = S_OK; - - // Run EVR watcher - if(pSelf->pDisplayWatcher) { - CHECK_HR(hr = pSelf->pDisplayWatcher->Start()); - } - - // Run the media session. - CHECK_HR(hr = MFUtils::RunSession(pSelf->pSession, pSelf->pTopologyFull)); - - // Start asynchronous watcher thread - pSelf->bStarted = true; - int ret = tsk_thread_create(&pSelf->ppTread[0], RunSessionThread, pSelf); - if(ret != 0) { - TSK_DEBUG_ERROR("Failed to create thread"); - hr = E_FAIL; - pSelf->bStarted = false; - if(pSelf->ppTread[0]){ - tsk_thread_join(&pSelf->ppTread[0]); - } - MFUtils::ShutdownSession(pSelf->pSession, pSelf->pSource); - CHECK_HR(hr = E_FAIL); - } + plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; + + if(!pSelf) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if(pSelf->bStarted) { + TSK_DEBUG_INFO("MF video consumer already started"); + return 0; + } + if(!pSelf->bPrepared) { + TSK_DEBUG_ERROR("MF video consumer not prepared"); + return -1; + } + + HRESULT hr = S_OK; + + // Run EVR watcher + if(pSelf->pDisplayWatcher) { + CHECK_HR(hr = pSelf->pDisplayWatcher->Start()); + } + + // Run the media session. + CHECK_HR(hr = MFUtils::RunSession(pSelf->pSession, pSelf->pTopologyFull)); + + // Start asynchronous watcher thread + pSelf->bStarted = true; + int ret = tsk_thread_create(&pSelf->ppTread[0], RunSessionThread, pSelf); + if(ret != 0) { + TSK_DEBUG_ERROR("Failed to create thread"); + hr = E_FAIL; + pSelf->bStarted = false; + if(pSelf->ppTread[0]) { + tsk_thread_join(&pSelf->ppTread[0]); + } + MFUtils::ShutdownSession(pSelf->pSession, pSelf->pSource); + CHECK_HR(hr = E_FAIL); + } bail: - return SUCCEEDED(hr) ? 0 : -1; + return SUCCEEDED(hr) ? 0 : -1; } static int plugin_win_mf_consumer_video_consume(tmedia_consumer_t* self, const void* buffer, tsk_size_t size, const tsk_object_t* proto_hdr) { - plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; - - HRESULT hr = S_OK; - - if(!pSelf || !buffer || !size) { - TSK_DEBUG_ERROR("Invalid parameter"); - CHECK_HR(hr = E_INVALIDARG); - } - - if(!pSelf->bStarted) { - TSK_DEBUG_INFO("MF video consumer not started"); - CHECK_HR(hr = E_FAIL); - } - if(!pSelf->pSource) { - TSK_DEBUG_ERROR("No video custom source"); - CHECK_HR(hr = E_FAIL); - } - - if(pSelf->nNegWidth != TMEDIA_CONSUMER(pSelf)->video.in.width || pSelf->nNegHeight != TMEDIA_CONSUMER(pSelf)->video.in.height){ - TSK_DEBUG_INFO("Negotiated and input video sizes are different:%d#%d or %d#%d", - pSelf->nNegWidth, TMEDIA_CONSUMER(pSelf)->video.in.width, - pSelf->nNegHeight, TMEDIA_CONSUMER(pSelf)->video.in.height); - // Update media type - CHECK_HR(hr = MFSetAttributeSize(pSelf->pOutType, MF_MT_FRAME_SIZE, TMEDIA_CONSUMER(pSelf)->video.in.width, TMEDIA_CONSUMER(pSelf)->video.in.height)); - CHECK_HR(hr = MFSetAttributeRatio(pSelf->pOutType, MF_MT_FRAME_RATE, TMEDIA_CONSUMER(pSelf)->video.fps, 1)); - - CHECK_HR(hr = pSelf->pSession->ClearTopologies()); - - // - // FIXME: Using same EVR when the size is just swapped (e.g. [640, 480] -> [480, 640]) doesn't work while other changes does (e.g. [352, 288] -> [640, 480]) - // /!\This look like a bug in Media Foundation - // - if(pSelf->nNegWidth == TMEDIA_CONSUMER(pSelf)->video.in.height && pSelf->nNegHeight == TMEDIA_CONSUMER(pSelf)->video.in.width) // swapped? - { - TSK_DEBUG_INFO("/!\\ Size swapped"); - - IMFActivate* pSinkActivate = NULL; - IMFTopology* pTopologyPartial = NULL; - hr = MFCreateVideoRendererActivate(pSelf->hWindow, &pSinkActivate); - if(FAILED(hr)) goto end_of_swapping; - hr = MFUtils::CreateTopology( - pSelf->pSource, - pSelf->pDecoder ? pSelf->pDecoder->GetMFT() : NULL, - pSinkActivate, - NULL/*Preview*/, - pSelf->pOutType, - &pTopologyPartial); - if(FAILED(hr)) goto end_of_swapping; - - if(SUCCEEDED(hr)) { - SafeRelease(&pSelf->pSinkActivate); - SafeRelease(&pSelf->pTopologyPartial); - pSelf->pSinkActivate = pSinkActivate; pSinkActivate = NULL; - pSelf->pTopologyPartial = pTopologyPartial; pTopologyPartial = NULL; - - } - + plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; + + HRESULT hr = S_OK; + + if(!pSelf || !buffer || !size) { + TSK_DEBUG_ERROR("Invalid parameter"); + CHECK_HR(hr = E_INVALIDARG); + } + + if(!pSelf->bStarted) { + TSK_DEBUG_INFO("MF video consumer not started"); + CHECK_HR(hr = E_FAIL); + } + if(!pSelf->pSource) { + TSK_DEBUG_ERROR("No video custom source"); + CHECK_HR(hr = E_FAIL); + } + + if(pSelf->nNegWidth != TMEDIA_CONSUMER(pSelf)->video.in.width || pSelf->nNegHeight != TMEDIA_CONSUMER(pSelf)->video.in.height) { + TSK_DEBUG_INFO("Negotiated and input video sizes are different:%d#%d or %d#%d", + pSelf->nNegWidth, TMEDIA_CONSUMER(pSelf)->video.in.width, + pSelf->nNegHeight, TMEDIA_CONSUMER(pSelf)->video.in.height); + // Update media type + CHECK_HR(hr = MFSetAttributeSize(pSelf->pOutType, MF_MT_FRAME_SIZE, TMEDIA_CONSUMER(pSelf)->video.in.width, TMEDIA_CONSUMER(pSelf)->video.in.height)); + CHECK_HR(hr = MFSetAttributeRatio(pSelf->pOutType, MF_MT_FRAME_RATE, TMEDIA_CONSUMER(pSelf)->video.fps, 1)); + + CHECK_HR(hr = pSelf->pSession->ClearTopologies()); + + // + // FIXME: Using same EVR when the size is just swapped (e.g. [640, 480] -> [480, 640]) doesn't work while other changes does (e.g. [352, 288] -> [640, 480]) + // /!\This look like a bug in Media Foundation + // + if(pSelf->nNegWidth == TMEDIA_CONSUMER(pSelf)->video.in.height && pSelf->nNegHeight == TMEDIA_CONSUMER(pSelf)->video.in.width) { // swapped? + TSK_DEBUG_INFO("/!\\ Size swapped"); + + IMFActivate* pSinkActivate = NULL; + IMFTopology* pTopologyPartial = NULL; + hr = MFCreateVideoRendererActivate(pSelf->hWindow, &pSinkActivate); + if(FAILED(hr)) { + goto end_of_swapping; + } + hr = MFUtils::CreateTopology( + pSelf->pSource, + pSelf->pDecoder ? pSelf->pDecoder->GetMFT() : NULL, + pSinkActivate, + NULL/*Preview*/, + pSelf->pOutType, + &pTopologyPartial); + if(FAILED(hr)) { + goto end_of_swapping; + } + + if(SUCCEEDED(hr)) { + SafeRelease(&pSelf->pSinkActivate); + SafeRelease(&pSelf->pTopologyPartial); + pSelf->pSinkActivate = pSinkActivate; + pSinkActivate = NULL; + pSelf->pTopologyPartial = pTopologyPartial; + pTopologyPartial = NULL; + + } + end_of_swapping: - SafeRelease(&pSinkActivate); - SafeRelease(&pTopologyPartial); - CHECK_HR(hr); - } - - // Set media type again (not required but who know) - CHECK_HR(hr = MFUtils::SetMediaType(pSelf->pSource, pSelf->pOutType)); - - // Rebuild topology using the partial one - IMFTopology* pTopologyFull = NULL; - hr = MFUtils::ResolveTopology(pSelf->pTopologyPartial, &pTopologyFull); - if(SUCCEEDED(hr)){ - SafeRelease(&pSelf->pTopologyFull); - pSelf->pTopologyFull = pTopologyFull; pTopologyFull = NULL; - } - SafeRelease(&pTopologyFull); - CHECK_HR(hr); - - // Find Main Sink - IMFMediaSink* pMediaSink = NULL; - hr = MFUtils::FindNodeObject(pSelf->pTopologyFull, MFUtils::g_ullTopoIdSinkMain, (void**)&pMediaSink); - if(SUCCEEDED(hr)) { - if(pSelf->pDisplayWatcher){ - delete pSelf->pDisplayWatcher, pSelf->pDisplayWatcher = NULL; - } - pSelf->pDisplayWatcher = new DisplayWatcher(pSelf->hWindow, pMediaSink, hr); - if(SUCCEEDED(hr) && pSelf->bStarted) { - hr = pSelf->pDisplayWatcher->Start(); - } - } - SafeRelease(&pMediaSink); - CHECK_HR(hr); - - // Update the topology associated to the media session - CHECK_HR(hr = pSelf->pSession->SetTopology(MFSESSION_SETTOPOLOGY_IMMEDIATE, pSelf->pTopologyFull)); - - // Update negotiated width and height - pSelf->nNegWidth = TMEDIA_CONSUMER(pSelf)->video.in.width; - pSelf->nNegHeight = TMEDIA_CONSUMER(pSelf)->video.in.height; - } - - // Deliver buffer - CHECK_HR(hr = pSelf->pSource->CopyVideoBuffer(pSelf->nNegWidth, pSelf->nNegHeight, buffer, size)); + SafeRelease(&pSinkActivate); + SafeRelease(&pTopologyPartial); + CHECK_HR(hr); + } + + // Set media type again (not required but who know) + CHECK_HR(hr = MFUtils::SetMediaType(pSelf->pSource, pSelf->pOutType)); + + // Rebuild topology using the partial one + IMFTopology* pTopologyFull = NULL; + hr = MFUtils::ResolveTopology(pSelf->pTopologyPartial, &pTopologyFull); + if(SUCCEEDED(hr)) { + SafeRelease(&pSelf->pTopologyFull); + pSelf->pTopologyFull = pTopologyFull; + pTopologyFull = NULL; + } + SafeRelease(&pTopologyFull); + CHECK_HR(hr); + + // Find Main Sink + IMFMediaSink* pMediaSink = NULL; + hr = MFUtils::FindNodeObject(pSelf->pTopologyFull, MFUtils::g_ullTopoIdSinkMain, (void**)&pMediaSink); + if(SUCCEEDED(hr)) { + if(pSelf->pDisplayWatcher) { + delete pSelf->pDisplayWatcher, pSelf->pDisplayWatcher = NULL; + } + pSelf->pDisplayWatcher = new DisplayWatcher(pSelf->hWindow, pMediaSink, hr); + if(SUCCEEDED(hr) && pSelf->bStarted) { + hr = pSelf->pDisplayWatcher->Start(); + } + } + SafeRelease(&pMediaSink); + CHECK_HR(hr); + + // Update the topology associated to the media session + CHECK_HR(hr = pSelf->pSession->SetTopology(MFSESSION_SETTOPOLOGY_IMMEDIATE, pSelf->pTopologyFull)); + + // Update negotiated width and height + pSelf->nNegWidth = TMEDIA_CONSUMER(pSelf)->video.in.width; + pSelf->nNegHeight = TMEDIA_CONSUMER(pSelf)->video.in.height; + } + + // Deliver buffer + CHECK_HR(hr = pSelf->pSource->CopyVideoBuffer(pSelf->nNegWidth, pSelf->nNegHeight, buffer, size)); bail: - return SUCCEEDED(hr) ? 0 : -1; + return SUCCEEDED(hr) ? 0 : -1; } static int plugin_win_mf_consumer_video_pause(tmedia_consumer_t* self) { - plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; + plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; - if(!pSelf){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - if(!pSelf->bStarted) - { - TSK_DEBUG_INFO("MF video producer not started"); - return 0; - } + if(!pSelf) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + if(!pSelf->bStarted) { + TSK_DEBUG_INFO("MF video producer not started"); + return 0; + } - HRESULT hr = MFUtils::PauseSession(pSelf->pSession); + HRESULT hr = MFUtils::PauseSession(pSelf->pSession); - return SUCCEEDED(hr) ? 0 : -1; + return SUCCEEDED(hr) ? 0 : -1; } static int plugin_win_mf_consumer_video_stop(tmedia_consumer_t* self) { - plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; + plugin_win_mf_consumer_video_t* pSelf = (plugin_win_mf_consumer_video_t*)self; - if(!pSelf){ + if(!pSelf) { TSK_DEBUG_ERROR("Invalid parameter"); return -1; } HRESULT hr = S_OK; - // stop EVR watcher - if(pSelf->pDisplayWatcher) { - hr = pSelf->pDisplayWatcher->Stop(); - } + // stop EVR watcher + if(pSelf->pDisplayWatcher) { + hr = pSelf->pDisplayWatcher->Stop(); + } // for the thread pSelf->bStarted = false; hr = MFUtils::ShutdownSession(pSelf->pSession, NULL); // stop session to wakeup the asynchronous thread - if(pSelf->ppTread[0]){ + if(pSelf->ppTread[0]) { tsk_thread_join(&pSelf->ppTread[0]); } hr = MFUtils::ShutdownSession(NULL, pSelf->pSource); // stop source to release the camera - // next start() will be called after prepare() - return _plugin_win_mf_consumer_video_unprepare(pSelf); + // next start() will be called after prepare() + return _plugin_win_mf_consumer_video_unprepare(pSelf); } static int _plugin_win_mf_consumer_video_unprepare(plugin_win_mf_consumer_video_t* pSelf) { - if(!pSelf){ - TSK_DEBUG_ERROR("Invalid parameter"); - return -1; - } - - if(pSelf->bStarted) { - // plugin_win_mf_producer_video_stop(TMEDIA_PRODUCER(pSelf)); - TSK_DEBUG_ERROR("Consumer must be stopped before calling unprepare"); - } - - if(pSelf->pDisplayWatcher) { - pSelf->pDisplayWatcher->Stop(); - } - if(pSelf->pSource){ - pSelf->pSource->Shutdown(); - pSelf->pSource = NULL; - } - if(pSelf->pSession){ + if(!pSelf) { + TSK_DEBUG_ERROR("Invalid parameter"); + return -1; + } + + if(pSelf->bStarted) { + // plugin_win_mf_producer_video_stop(TMEDIA_PRODUCER(pSelf)); + TSK_DEBUG_ERROR("Consumer must be stopped before calling unprepare"); + } + + if(pSelf->pDisplayWatcher) { + pSelf->pDisplayWatcher->Stop(); + } + if(pSelf->pSource) { + pSelf->pSource->Shutdown(); + pSelf->pSource = NULL; + } + if(pSelf->pSession) { pSelf->pSession->Shutdown(); - pSelf->pSession = NULL; + pSelf->pSession = NULL; } - SafeRelease(&pSelf->pDecoder); + SafeRelease(&pSelf->pDecoder); SafeRelease(&pSelf->pSession); SafeRelease(&pSelf->pSource); SafeRelease(&pSelf->pSinkActivate); SafeRelease(&pSelf->pTopologyFull); - SafeRelease(&pSelf->pTopologyPartial); - SafeRelease(&pSelf->pOutType); + SafeRelease(&pSelf->pTopologyPartial); + SafeRelease(&pSelf->pOutType); - if(pSelf->pDisplayWatcher) { - delete pSelf->pDisplayWatcher; - pSelf->pDisplayWatcher = NULL; - } + if(pSelf->pDisplayWatcher) { + delete pSelf->pDisplayWatcher; + pSelf->pDisplayWatcher = NULL; + } - pSelf->bPrepared = false; + pSelf->bPrepared = false; - return 0; + return 0; } @@ -1519,102 +1450,98 @@ static int _plugin_win_mf_consumer_video_unprepare(plugin_win_mf_consumer_video_ /* constructor */ static tsk_object_t* plugin_win_mf_consumer_video_ctor(tsk_object_t * self, va_list * app) { - MFUtils::Startup(); - - plugin_win_mf_consumer_video_t *pSelf = (plugin_win_mf_consumer_video_t *)self; - if(pSelf){ - /* init base */ - tmedia_consumer_init(TMEDIA_CONSUMER(pSelf)); - TMEDIA_CONSUMER(pSelf)->video.display.chroma = tmedia_chroma_yuv420p; - TMEDIA_CONSUMER(pSelf)->decoder.codec_id = tmedia_codec_id_none; // means accept RAW fames - - /* init self */ - // consumer->create_on_ui_thread = tsk_true; - TMEDIA_CONSUMER(pSelf)->video.fps = 15; - TMEDIA_CONSUMER(pSelf)->video.display.width = 0; // use codec value - TMEDIA_CONSUMER(pSelf)->video.display.height = 0; // use codec value - TMEDIA_CONSUMER(pSelf)->video.display.auto_resize = tsk_true; - - TSK_DEBUG_INFO("Create WinMF video consumer"); - } - return self; + MFUtils::Startup(); + + plugin_win_mf_consumer_video_t *pSelf = (plugin_win_mf_consumer_video_t *)self; + if(pSelf) { + /* init base */ + tmedia_consumer_init(TMEDIA_CONSUMER(pSelf)); + TMEDIA_CONSUMER(pSelf)->video.display.chroma = tmedia_chroma_yuv420p; + TMEDIA_CONSUMER(pSelf)->decoder.codec_id = tmedia_codec_id_none; // means accept RAW fames + + /* init self */ + // consumer->create_on_ui_thread = tsk_true; + TMEDIA_CONSUMER(pSelf)->video.fps = 15; + TMEDIA_CONSUMER(pSelf)->video.display.width = 0; // use codec value + TMEDIA_CONSUMER(pSelf)->video.display.height = 0; // use codec value + TMEDIA_CONSUMER(pSelf)->video.display.auto_resize = tsk_true; + + TSK_DEBUG_INFO("Create WinMF video consumer"); + } + return self; } /* destructor */ static tsk_object_t* plugin_win_mf_consumer_video_dtor(tsk_object_t * self) -{ - plugin_win_mf_consumer_video_t *pSelf = (plugin_win_mf_consumer_video_t *)self; - if(pSelf){ - /* stop */ - if(pSelf->bStarted){ - plugin_win_mf_consumer_video_stop(TMEDIA_CONSUMER(pSelf)); - } - - /* deinit base */ - tmedia_consumer_deinit(TMEDIA_CONSUMER(pSelf)); - /* deinit self */ - _plugin_win_mf_consumer_video_unprepare(pSelf); - } - - return self; +{ + plugin_win_mf_consumer_video_t *pSelf = (plugin_win_mf_consumer_video_t *)self; + if(pSelf) { + /* stop */ + if(pSelf->bStarted) { + plugin_win_mf_consumer_video_stop(TMEDIA_CONSUMER(pSelf)); + } + + /* deinit base */ + tmedia_consumer_deinit(TMEDIA_CONSUMER(pSelf)); + /* deinit self */ + _plugin_win_mf_consumer_video_unprepare(pSelf); + } + + return self; } /* object definition */ -static const tsk_object_def_t plugin_win_mf_consumer_video_def_s = -{ - sizeof(plugin_win_mf_consumer_video_t), - plugin_win_mf_consumer_video_ctor, - plugin_win_mf_consumer_video_dtor, - tsk_null, +static const tsk_object_def_t plugin_win_mf_consumer_video_def_s = { + sizeof(plugin_win_mf_consumer_video_t), + plugin_win_mf_consumer_video_ctor, + plugin_win_mf_consumer_video_dtor, + tsk_null, }; /* plugin definition*/ -static const tmedia_consumer_plugin_def_t plugin_win_mf_consumer_video_plugin_def_s = -{ - &plugin_win_mf_consumer_video_def_s, - - tmedia_video, - "Media Foundation video consumer", - - plugin_win_mf_consumer_video_set, - plugin_win_mf_consumer_video_prepare, - plugin_win_mf_consumer_video_start, - plugin_win_mf_consumer_video_consume, - plugin_win_mf_consumer_video_pause, - plugin_win_mf_consumer_video_stop +static const tmedia_consumer_plugin_def_t plugin_win_mf_consumer_video_plugin_def_s = { + &plugin_win_mf_consumer_video_def_s, + + tmedia_video, + "Media Foundation video consumer", + + plugin_win_mf_consumer_video_set, + plugin_win_mf_consumer_video_prepare, + plugin_win_mf_consumer_video_start, + plugin_win_mf_consumer_video_consume, + plugin_win_mf_consumer_video_pause, + plugin_win_mf_consumer_video_stop }; const tmedia_consumer_plugin_def_t *plugin_win_mf_consumer_video_plugin_def_t = &plugin_win_mf_consumer_video_plugin_def_s; // Run session async thread static void* TSK_STDCALL RunSessionThread(void *pArg) { - plugin_win_mf_consumer_video_t *pSelf = (plugin_win_mf_consumer_video_t *)pArg; - HRESULT hrStatus = S_OK; - HRESULT hr = S_OK; - IMFMediaEvent *pEvent = NULL; - MediaEventType met; - - TSK_DEBUG_INFO("RunSessionThread (MF video consumer) - ENTER"); - - while(pSelf->bStarted){ - CHECK_HR(hr = pSelf->pSession->GetEvent(0, &pEvent)); - CHECK_HR(hr = pEvent->GetStatus(&hrStatus)); - CHECK_HR(hr = pEvent->GetType(&met)); - - if (FAILED(hrStatus) /*&& hrStatus != MF_E_NO_SAMPLE_TIMESTAMP*/) - { - TSK_DEBUG_ERROR("Session error: 0x%x (event id: %d)\n", hrStatus, met); - hr = hrStatus; - goto bail; - } - if (met == MESessionEnded) - { - break; - } - SafeRelease(&pEvent); - } + plugin_win_mf_consumer_video_t *pSelf = (plugin_win_mf_consumer_video_t *)pArg; + HRESULT hrStatus = S_OK; + HRESULT hr = S_OK; + IMFMediaEvent *pEvent = NULL; + MediaEventType met; + + TSK_DEBUG_INFO("RunSessionThread (MF video consumer) - ENTER"); + + while(pSelf->bStarted) { + CHECK_HR(hr = pSelf->pSession->GetEvent(0, &pEvent)); + CHECK_HR(hr = pEvent->GetStatus(&hrStatus)); + CHECK_HR(hr = pEvent->GetType(&met)); + + if (FAILED(hrStatus) /*&& hrStatus != MF_E_NO_SAMPLE_TIMESTAMP*/) { + TSK_DEBUG_ERROR("Session error: 0x%x (event id: %d)\n", hrStatus, met); + hr = hrStatus; + goto bail; + } + if (met == MESessionEnded) { + break; + } + SafeRelease(&pEvent); + } bail: - TSK_DEBUG_INFO("RunSessionThread (MF video consumer) - EXIT"); + TSK_DEBUG_INFO("RunSessionThread (MF video consumer) - EXIT"); - return NULL; + return NULL; } #endif /* PLUGIN_MF_CV_USE_D3D9 */
\ No newline at end of file |