近来看DirectX 9.0文档,越来越觉得它功能的强大。结合目前解决的一个问题: 即采集多个视频源的一帧到一张位图。它需要用到DirectX中的VMR。
VMR是新一代的video renderer,全称为Video Mixing Renderer,它分为VMR7和VMR9,VMR7基于DirectDraw7,只限于Windows XP;VMR9基于Direct3D9。因为我的例子可能会用于Windows 2000,所以我采用了可用于所有支持DirectX平台的VMR9。
VMR9可以使用3种工作模式,分别为windowed,windowless,renderless模式。后两种模式多用于游戏中。测试例子中用的是windowless模式。
先看下程序实现的截图和graph图:
下面开始具体的程序实现:
视频设备的枚举在我的简化MFC版amcp中有过描述,这里主要是VMR9的创建与设定。
另外生成graph的方法如连接PINs也是采用简化MFC版amcp中描述的Capture Graph Builder中的方法。
程序中需要的成员变量:
IVMRWindowlessControl9
*m_pWCVMR9; // VMR9的WINDOWLESS模式控制
IVMRMixerControl9
*m_pMCVMR9; // VMR9的Mix控制
IBaseFilter
* m_pBFVMR9;// 用于创建VMR9
创建和配置VMR9:
HRESULT CMultiImageDlg::AddVideoMixingRendererToFG()
{
// create VMR9
HRESULT hRes = CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC, IID_IBaseFilter, (LPVOID *)&m_pBFVMR9);
if(SUCCEEDED(hRes))
{
// add to filter graph
hRes = m_pGraphBuilder->AddFilter(m_pBFVMR9, L"Video Mixing Renderer 9");
if(SUCCEEDED(hRes))
{
// Test VMRConfig, VMRMonitorConfig
IVMRFilterConfig9* pConfig;
HRESULT hRes2 = m_pBFVMR9->QueryInterface(IID_IVMRFilterConfig9, (LPVOID *)&pConfig);
if(SUCCEEDED(hRes2))
{
// VMR9 already default to 4 input pins
hRes2 = pConfig->SetNumberOfStreams(4);
// windowless mode
hRes2 = pConfig->SetRenderingMode(VMR9Mode_Windowless);
// use overlays if available
hRes2 = pConfig->SetRenderingPrefs(RenderPrefs_AllowOverlays);
pConfig->Release();
}
// query control
hRes = m_pBFVMR9->QueryInterface(IID_IVMRWindowlessControl9, (LPVOID *)&m_pWCVMR9);
}
}
if(m_pBFVMR9)
{
m_pBFVMR9->Release();
}
if(SUCCEEDED(hRes))
{
// set owner window
HRESULT hr = m_pWCVMR9->SetVideoClippingWindow(m_hWnd);
// to preserve the aspect ratioof the source
hr = m_pWCVMR9->SetAspectRatioMode(VMR_ARMODE_LETTER_BOX);
}
else
{
if(m_pWCVMR9)
{
m_pWCVMR9->Release();
m_pWCVMR9 = NULL;
}
}
return hRes;
}
另外可以在WM_PAINT中设置视频显示的重绘、WM_DISPLAYCHANGE中设置显示模式的改变、和在WM_SIZE中再次设置视频的位置。
对于视频输出矩形的设置:
对于多个输出流,VMR9通过一个”composition space”来设置它们的位置。在这个”composition space”中,可视视频矩形的坐标设置为(0.0, 0.0)到(1.0, 1.0)。所以如果有多个视频要布局,如本例程序中显示的那样,可以设置为:{0.0F, 0.0F, 0.5F, 0.5F, 1.0F}, {0.5F, 0.5F, 1.0F, 1.0F, 1.0F},数组中的最后一个为alpha值。通过数组中的参数可以看出,各个输出矩形可以设置输出比例和透明度。
最后,因为VMR9的input pins是连接多个视频源,所以通过它的接口GetCurrentImage得到输出视频的当前帧。
水平有限,不理解处可以参看DX文档。