VMR 无窗口模式
[与此页面关联的功能(DirectShow)是一项旧功能。 它已被 MediaPlayer、IMFMediaEngine取代,并在媒体基金会 音频/视频捕获。 这些功能已针对 Windows 10 和 Windows 11 进行了优化。 Microsoft强烈建议新代码尽可能使用 MediaPlayer、IMFMediaEngine 和 Media Foundation 中的音频/视频捕获,而不是 DirectShow。 Microsoft建议重写使用旧 API 的现有代码,以尽可能使用新 API。]
无窗口模式是应用程序在应用程序窗口中呈现视频的首选方法。 在无窗口模式下,视频混合呈现器不会加载其窗口管理器组件,因此不支持 IBasicVideo 或 IVideoWindow 接口。 相反,应用程序会提供播放窗口,并在 VMR 的工作区中设置一个目标矩形来绘制视频。 VMR 使用 DirectDraw 剪辑器对象来确保视频被剪裁到应用程序的窗口,并且不会显示在任何其他窗口中。 VMR 不会将应用程序的窗口子类化或安装任何系统/进程挂钩。
在无窗口模式下,连接期间和转换为运行状态的事件序列如下所示:
- 上游筛选器建议媒体类型,VMR 接受或拒绝该类型。
- 如果接受媒体类型,VMR 将调用分配器演示者以获取 DirectDraw 图面。 如果成功创建图面,则引脚连接,并且 VMR 已准备好转换为运行状态。
- 筛选器图运行时,解码器调用 GetBuffer 从分配器获取媒体示例。 VMR 查询分配器演示者,以确保其 DirectDraw 图面上的像素深度、矩形大小和其他参数与传入视频兼容。 如果它们兼容,则 VMR 会将 DirectDraw 图面返回到解码器。 解码器解码到图面后,VMR 的核心同步单元将验证时间戳。 本单元将阻止 接收 呼叫,直到演示时间到达。 此时,VMR 会在分配器演示器上调用 PresentImage,该分配器向图形卡呈现图面。
下图显示了具有多个输入流的无窗口模式下的 VMR。
在无窗口模式下
为无窗口模式配置 VMR-7
若要为无窗口模式配置 VMR-7,请在连接任何 VMR 的输入引脚之前执行以下步骤:
创建筛选器并将其添加到图形。
使用VMRMode_Windowless标志调用 IVMRFilterConfig::SetRenderingMode 方法。
(可选)通过调用 IVMRFilterConfig::SetNumberOfStreams为多个输入流配置 VMR。 VMR 为每个流创建一个输入引脚。 使用 IVMRMixerControl 接口设置流的 Z 顺序和其他参数。 有关详细信息,请参阅 具有多个流(混合模式)的 VMR。
如果不调用 setNumberOfStreams ,则 VMR-7 默认为一个输入引脚。 连接输入引脚后,无法更改引脚数。
调用 IVMRWindowlessControl::SetVideoClippingWindow 以指定呈现的视频将在其中显示的窗口。
完成这些步骤后,可以连接 VMR 筛选器的输入引脚。 可以使用智能连接方法(例如 IGraphBuilder::RenderFile)或使用 Capture Graph Builder 的 ICaptureGraphBuilder2::RenderStream 方法生成图形,例如直接连接图钉。 有关详细信息,请参阅 常规 Graph-Building 技术。
若要在应用程序窗口中设置视频的位置,请调用 IVMRWindowlessControl::SetVideoPosition 方法。 IVMRWindowlessControl::GetNativeVideoSize 方法返回本机视频大小。 在播放期间,应用程序应通知 VMR 以下 Windows 消息:
- WM_PAINT:调用 IVMRWindowlessControl::RepaintVideo 以重新画出映像。
- WM_DISPLAYCHANGE:调用 IVMRWindowlessControl::D isplayModeChanged。 VMR 执行在新的分辨率或颜色深度上显示视频所需的任何作。
- WM_SIZE:根据需要重新计算视频的位置并调用 SetVideoPosition。
注意
MFC 应用程序必须定义空WM_ERASEBKGND消息处理程序,否则视频显示区域将无法正确重绘。
为无窗口模式配置 VMR-9
若要为无窗口模式配置 VMR-9,请使用针对无窗口模式的 VMR-7 所述的步骤,但使用 IVMRFilterConfig9 和 IVMRWindowlessControl9 接口。 唯一的显著区别是 VMR-9 默认创建四个输入引脚,而不是一个输入引脚。 因此,如果混合了 4 个以上的视频流,则只需调用 SetNumberOfStreams。
示例代码
以下代码演示如何创建 VMR-7 筛选器,将其添加到 DirectShow 筛选器图,然后将 VMR 置于无窗口模式。 对于 VMR-9,请使用 CoCreateInstance 和相应的 VMR-9 接口中的CLSID_VideoMixingRenderer9。
HRESULT InitializeWindowlessVMR(
HWND hwndApp, // Application window.
IFilterGraph* pFG, // Pointer to the Filter Graph Manager.
IVMRWindowlessControl** ppWc, // Receives the interface.
DWORD dwNumStreams, // Number of streams to use.
BOOL fBlendAppImage // Are we alpha-blending a bitmap?
)
{
IBaseFilter* pVmr = NULL;
IVMRWindowlessControl* pWc = NULL;
*ppWc = NULL;
// Create the VMR and add it to the filter graph.
HRESULT hr = CoCreateInstance(CLSID_VideoMixingRenderer, NULL,
CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr);
if (FAILED(hr))
{
return hr;
}
hr = pFG->AddFilter(pVmr, L"Video Mixing Renderer");
if (FAILED(hr))
{
pVmr->Release();
return hr;
}
// Set the rendering mode and number of streams.
IVMRFilterConfig* pConfig;
hr = pVmr->QueryInterface(IID_IVMRFilterConfig, (void**)&pConfig);
if (SUCCEEDED(hr))
{
pConfig->SetRenderingMode(VMRMode_Windowless);
// Set the VMR-7 to mixing mode if you want more than one video
// stream, or you want to mix a static bitmap over the video.
// (The VMR-9 defaults to mixing mode with four inputs.)
if (dwNumStreams > 1 || fBlendAppImage)
{
pConfig->SetNumberOfStreams(dwNumStreams);
}
pConfig->Release();
hr = pVmr->QueryInterface(IID_IVMRWindowlessControl, (void**)&pWc);
if (SUCCEEDED(hr))
{
pWc->SetVideoClippingWindow(hwndApp);
*ppWc = pWc; // The caller must release this interface.
}
}
pVmr->Release();
// Now the VMR can be connected to other filters.
return hr;
}
相关主题