Directshow 學習入門

一、視頻播放(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); 
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章