VMR 无窗口模式
[与此页面关联的功能 DirectShow 是旧版功能。 它已被 MediaPlayer、 IMFMediaEngine 和 Media Foundation 中的音频/视频捕获所取代。 这些功能已针对Windows 10和Windows 11进行了优化。 Microsoft 强烈建议新代码尽可能在 Media Foundation 中使用 MediaPlayer、 IMFMediaEngine 和 音频/视频捕获 ,而不是 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 等智能连接方法,或使用捕获图形生成器的 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 默认创建四个输入引脚,而不是一个输入引脚。 因此,只需在混合四个以上的视频流时调用 SetNumberOfStreams 。
示例代码
以下代码演示如何创建 VMR-7 筛选器,将其添加到 DirectShow 筛选器图,然后将 VMR 置于无窗口模式。 对于 VMR-9,请在 CoCreateInstance 中使用CLSID_VideoMixingRenderer9和相应的 VMR-9 接口。
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;
}
相关主题