一、视频播放(Video Rendering)
视频播放(Video Rendering)
dshow的视频提交过滤器可以在窗口模式和无窗口模式下工作。在窗口模式下,过滤器创建一个自己的窗口,在里面播放视频。在无窗口模式下,过滤器直接将视频在应用程序提供的窗口上显示,过滤器本身不创建窗口。
窗口模式
在窗口模式下,视频提交过滤器创建一个窗口,然后将视频祯帖到窗口上,你可以将这个窗口帖到你的应用程序的窗口。
Video Renderer只支持窗口模式,VMR-7 and VMR-9缺省的是窗口模式,也支持无窗口模式。
为了在你的应用程序中显示视频,你可以将视频窗口设置成应用程序的子窗口。你可以通过
IVideoWindow *pVidWin = NULL; pGraph->QueryInterface(IID_IVideoWindow, (void **)&g_pVidWin); pVidWin->put_Owner((OAHWND)hwnd); pVidWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS); RECT grc; GetClientRect(hwnd, &grc); pVidWin->SetWindowPosition(0, 0, grc.right, grc.bottom); |
结束时一定要清理现场:
pControl->Stop(); pVidWin->put_Visible(OAFALSE); pVidWin->put_Owner(NULL); |
无窗口模式
当采用无窗口的模式时,就没有必要暴露IVideoWindow接口了。
为了能够使用VMR的缺省行为,在构建Graph图之前必须要调整VMR。
1、创建一个过虑器图表管理器
2、创建一个VMR,加入到graph中
3、调用VMR的IVMRFilterConfig::SetRenderingMode方法设置VMRMode_Windowless标志。
4、调用IVMRWindowlessControl::SetVideoClippingWindow 给视频指定一个显示窗口。
然后调用IGraphBuilder::RenderFile或者其他的方法来创建其他的Graph。
下面的代码显示了如何创建一个VMR,将其添加到Graph,如何设置无窗口模式
HRESULT InitWindowlessVMR( HWND hwndApp, // Window to hold the video. IGraphBuilder* pGraph, // Pointer to the Filter Graph Manager. IVMRWindowlessControl** ppWc, // Receives a pointer to the VMR. ) { if (!pGraph || !ppWc) return E_POINTER; IBaseFilter* pVmr = NULL; IVMRWindowlessControl* pWc = NULL; // Create the VMR. HRESULT hr = CoCreateInstance(CLSID_VideoMixingRenderer, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr); if (FAILED(hr)) { return hr; } // Add the VMR to the filter graph. hr = pGraph->AddFilter(pVmr, L"Video Mixing Renderer"); if (FAILED(hr)) { pVmr->Release(); return hr; } // Set the rendering mode. IVMRFilterConfig* pConfig; hr = pVmr->QueryInterface(IID_IVMRFilterConfig, (void**)&pConfig); if (SUCCEEDED(hr)) { hr = pConfig->SetRenderingMode(VMRMode_Windowless); pConfig->Release(); } if (SUCCEEDED(hr)) { // Set the window. hr = pVmr->QueryInterface(IID_IVMRWindowlessControl, (void**)&pWc); if( SUCCEEDED(hr)) { hr = pWc->SetVideoClippingWindow(hwndApp); if (SUCCEEDED(hr)) { *ppWc = pWc; // Return this as an AddRef‘d pointer. } else { // An error occurred, so release the interface. pWc->Release(); } } } pVmr->Release(); return hr; } |
你也可以调用下面的函数
IVMRWindowlessControl *pWc = NULL; hr = InitWindowlessVMR(hwnd, pGraph, &g_pWc); if (SUCCEEDED(hr)) { // Build the graph. For example: pGraph->RenderFile(wszMyFileName, 0); // Release the VMR interface when you are done. pWc->Release(); } |
下面看看如何设置视频的位置
有两个矩形需要考虑,一个是源矩形,一个是目的矩形。源矩形决定开始播放视频的位置,目的矩形决定在窗口显示视频的区域。VMR将源矩形按照目的矩形的大小进行扩展。
IVMRWindowlessControl::SetVideoPosition可以设置两个矩形的大小,源矩形必须小于等于本地视频大小。你可以通过IVMRWindowlessControl::GetNativeVideoSize获取本地的视频区域大小。
// Find the native video size. long lWidth, lHeight; HRESULT hr = g_pWc->GetNativeVideoSize(&lWidth, &lHeight, NULL, NULL); if (SUCCEEDED(hr)) { RECT rcSrc, rcDest; // Set the source rectangle. SetRect(&rcSrc, 0, 0, lWidth/2, lHeight/2); // Get the window client area. GetClientRect(hwnd, &rcDest); // Set the destination rectangle. SetRect(&rcDest, 0, 0, rcDest.right/2, rcDest.bottom/2); // Set the video position. hr = g_pWc->SetVideoPosition(&rcSrc, &rcDest); } |