生成 DVD 筛选器图

[与此页面关联的功能 DirectShow 是一项旧功能。 它已被 MediaPlayerIMFMediaEngine媒体基金会中的音频/视频捕获取代。 这些功能已针对Windows 10和Windows 11进行了优化。 Microsoft 强烈建议新代码尽可能使用 MediaPlayerIMFMediaEngineMedia Foundation 中的音频/视频捕获 ,而不是 DirectShow。 如果可能,Microsoft 建议重写使用旧 API 的现有代码以使用新 API。]

与任何 DirectShow 应用程序一样,DVD 播放应用程序首先生成筛选器图。 DirectShow 提供以下用于 DVD 播放的组件:

DVD 播放还需要 MPEG-2 解码器。 第三方提供硬件和软件 MPEG-2 解码器。 首先,创建 DVD Graph Builder 对象的实例。

IDvdGraphBuilder *pBuild = NULL;
hr = CoCreateInstance(CLSID_DvdGraphBuilder, NULL, 
    CLSCTX_INPROC_SERVER, IID_IDvdGraphBuilder, (void **)&pBuild);

此时,可以在生成图形的其余部分之前选择和配置视频呈现器。 下一部分将更详细地介绍此步骤(可选)。 如果省略此步骤,DVD Graph 生成器会选择默认呈现器。 接下来,通过调用 IDvdGraphBuilder::RenderDvdVideoVolume 方法生成图形。

AM_DVD_RENDERSTATUS buildStatus;
hr = pBuild->RenderDvdVideoVolume(L"Z:\\video_ts", 0, &buildStatus);

第一个参数是包含 DVD 文件的目录的名称。 在 DVD 光盘上,这些文件位于名为 VIDEO_TS 的目录中。 如果第一个参数为 NULL,则 DVD Graph 生成器将使用包含 DVD 卷的第一个驱动器。

第二个参数包含用于选择解码器类型的各种可选标志, (硬件或软件) 和其他选项。

第三个参数是接收状态信息的 AM_DVD_RENDERSTATUS 结构。 如果 RenderDvdVideoVolume 方法返回S_FALSE,则表示调用部分成功 (或部分失败(如果你是悲观) )。 例如, 方法可能无法呈现子图片流,即使其他流已成功呈现。 如果 RenderDvdVideoVolume 方法返回错误代码或值S_FALSE,则可以检查 AM_DVD_RENDERSTATUS 结构以获取有关错误的详细信息。

接下来,通过调用 IDvdGraphBuilder::GetFiltergraph 获取指向筛选器关系图管理器的指针。 此方法返回指向筛选器关系图管理器的 IGraphBuilder 接口的指针。

IGraphBuilder *pGraph = NULL;
hr =  pBuild->GetFiltergraph(&m_pGraph);

使用 IDvdGraphBuilder::GetDvdInterface 方法检索 DVD 相关的接口,其中包括:

例如,以下代码返回 IDvdControl2 接口。

IDvdControl2 *pDvdControl = NULL;
hr = pBuild->GetDvdInterface(IID_IDvdControl2, (void**)&pDvdControl);

生成 DVD 播放筛选器图的建议方法是让 DVD Graph Builder 对象自动执行此操作。 下面和 DVD 示例应用程序中演示了此方法。 如果需要手动生成 DVD 筛选器图,可以遵循 DirectShow 文档中其他部分讨论的图形生成的基本规则。 通常,不应手动添加、删除、连接或断开由 DVD Graph 生成器创建的图形中的单个筛选器,因为这样做可能会混淆清理代码。

配置视频呈现器

DirectShow 提供了多个视频呈现器筛选器。 在生成图形之前,可以选择首选的视频呈现器。 通过调用 IDvdGraphBuilder::GetDvdInterface 并请求特定于该呈现器接口来选择呈现器:

如果在生成筛选器图之前请求这些接口中的任何一个,DVD 图形生成器将创建相应的视频呈现器。 稍后生成图形时,DVD Graph 生成器将尝试使用该呈现器。 但如果它无法使用所选呈现器生成图形,它可能会切换到另一个呈现器。 例如,MPEG-2 解码器可能与 VMR 筛选器不兼容,在这种情况下,DVD Graph 生成器将默认为覆盖混音器。

这些接口还让你有机会在将呈现器连接到解码器之前对其进行配置。 例如,可以将 VMR 设置为使用无窗口模式,而不是默认窗口模式。 有关视频呈现器的详细信息,请参阅主题 About Video Rendering in DirectShow

在 Windows XP 及更高版本上,DVD Graph 生成器始终使用 视频混合呈现器 7 (VMR-7) ,除非:

  • 调用方查询接口仅找到 Overlay Mixer,例如 IMixerPinConfig2。 这会向 DVD Graph 生成器发送一个提示,指出应用程序希望使用覆盖混音器而不是 VMR。 Windows 媒体播放器还有一个对话框选项来强制使用覆盖混音器。
  • 已安装的解码器与 VMR 不兼容。 在图形生成期间,新的 IAMDecoderCaps 接口用于检查解码器的 VMR 支持。 如果不存在,DVD 图形生成器将使用覆盖混音器。
  • 使用硬件解码器时,解码器无法连接到 视频端口管理器 (VPM) 。 如果硬件解码器无法使用 VPM,则它无法使用 VMR,因此 DVD Graph 生成器随后会尝试使用覆盖混音器生成图形。
  • 已知显示卡没有足够的资源和/或功能来支持 VMR,但在驱动程序中未正确报告此情况。 (DVD Graph Builder 专门排除了某些已知情况。)
  • 解码器和 VMR 之间的连接因任何原因而失败,通常是由于缺少 VRAM 来创建必要的图面。 在这些情况下,DVD 图形生成器会关闭 VMR 的使用,并尝试使用覆盖混音器来生成图形。

窗口模式

在窗口模式 (覆盖混音器或 VMR) ,呈现器创建自己的视频窗口。 若要使此窗口成为应用程序窗口的子窗口,请使用应用程序的句柄调用 IVideoWindow::p ut_Owner 。 另请调用 IVideoWindow::p ut_WindowStyle 以在呈现器的视频窗口中设置WS_CHILD和WS_CLIPSIBLINGS样式。 若要从呈现器的视频窗口获取鼠标消息,请使用应用程序窗口的句柄调用 IVideoWindow::p ut_MessageDrain 。 此方法设置“消息排出”-视频窗口将接收的任何鼠标消息转发到消息排出窗口。

pVideoWindow->put_Owner((OAHWND)hwnd);
pVideoWindow->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS);
pVideoWindow->put_MessageDrain((OAHWND)hwnd) ;

消息排出使选择 DVD 菜单按钮变得有些复杂。 假设视频窗口未填满应用程序的整个工作区,某些鼠标事件将落在视频窗口之外。 从视频窗口 获取鼠标事件时,应将其处理为 DVD 菜单导航。 不应处理来自视频窗口 外的 鼠标事件。 使用消息排出时,无法区分这两者。 此外,视频窗口中鼠标事件的坐标相对于视频窗口的工作区;但视频窗口外部的鼠标事件相对于应用程序的工作区。

无窗口模式

无窗口模式完全避免了鼠标消息的问题。 不需要消息排出,因为 VMR (或 EVR) 不会在无窗口模式下创建自己的窗口。 相反,它会直接绘制到应用程序窗口。 如果目标矩形小于应用程序工作区,则 DVD 导航器在计算 DVD 按钮位置时会考虑到这一点。 因此,当收到鼠标消息时,可以将坐标直接传递给 DVD 导航器,如菜单导航部分所述。

DVD 应用程序