在 DirectShow 中使用窗口媒体编解码器

Windows Media 音频和视频编码器和解码器对象最初设计并优化为使用 ASF 文件容器格式和 Windows Media Format SDK。 编解码器对象在 DirectShow 中适用于某些方案,即一次性 CBR 和视频流的基于质量的 VBR 编码。 但是,如果你考虑使用 ASF 以外的文件容器直接在 DirectShow 中使用编解码器对象,则应该提前了解某些行为和问题。

注意

如果要将独立编解码器与 DirectShow 配合使用,则可能只想将它们用作 DME。 换句话说,你将使用 IMediaObject 接口,而不是 IMFTransform

 

AVI 文件中的 WM 音频

可以使用 DirectShow 将 WMA 流编码为具有多路复用器筛选器的任何文件容器格式。 但是,Windows Media 音频和视频编解码器接口不支持 AVI 文件中的 WMA,因为使用默认的 DirectShow AVI 播放筛选器无法通过 WMA 流在 AVI 文件中保持音频视频同步。 有关详细信息,请参阅 在 AVI 文件中存储压缩媒体

音频编码器 DMO 输出不同持续时间的样本,即使在“固定比特率”模式下也是如此。 因此,它最适合使用时间戳的文件容器格式。 AVI 文件不提供每个音频示例或样本组的时间戳。 在 DirectShow 中,AVI 拆分器筛选器根据 AVI 流标头中 WAVEFORMATEX 结构中的 nAvgBytesPerSec 值,为每组样本 (每个音频帧) 生成时间戳。

此计算的基础假设是流中的所有音频样本的持续时间相等;但是,DMO 输出的样本持续时间不相等,因此 AVI 拆分器应用的时间戳不准确。 因此,如果不修改 AVI 拆分器或音频解码器 DMO,就不可能使用任何基于 DirectShow 的应用程序播放 AVI 文件以及同步的音频和视频流。Windows Media Audio 9 语音编解码器在某些情况下可以正常工作,但即使这样,在进行任何查找操作后也会失去同步,因此它实际上不能被视为可行的解决方案。

如果你有 MP3 编码器,则可以使用 WMV 和 MP3 为音频流创建 AVI 文件。 此类文件将在 Windows 媒体播放器 和其他基于 DirectShow 的应用程序中正确播放和查找,因为 AVI 拆分器包含 MP3 流的特殊处理代码。 另一个选项是使用未压缩的 PCM 音频,但显然生成的文件大小将比压缩的音频流大得多。 由于 DirectShow 示例应用程序创建 AVI 文件,因此它不演示如何使用音频编码器 DMO。

单次编码

视频编码器 DMO 在 DirectShow 中轻松适用于两种编码模式:CBR 和基于质量的 VBR。 只要在生成筛选器图时遵循正确的操作顺序(如示例应用程序所示),使用 AVI 多路复用器和文件编写器将 WMV 内容放入 AVI 文件中相对简单。

双传递编码

双通道编码模式需要更复杂的图形生成和流式处理方法,以防止 DMO 在开始第二次传递之前从第一个通道刷新其内容。 在双传递编码中,必须运行一次图形,以便 DMO 可以对文件数据执行预处理分析,然后回退图形并再次运行它,以便 DMO 可以执行实际编码。

当图形进入第二个传递的运行状态时,DMO 包装器在第一个样本上设置 DISCONTINUITY 标志,因为时间戳与第一个传递的最后一个时间戳不一样。 当 DMO(设计为不以这种方式在 DirectShow 中工作)收到 DISCONTINUITY 标志时,它将执行刷新并丢失从第一次传递存储的数据。 若要解决此问题,最佳解决方案可能是编写自定义 DMO 包装器筛选器,该筛选器不会在第一次传递后查找图形时设置 DISCONTINUITY 标志。 此 SDK 中的适用于 Windows (VfW) 的视频示例演示了如何执行双重编码。

隔行扫描内容

WMV 编码器 DMO 能够在保留隔行扫描内容的同时对交错内容进行编码,这对于从电视捕获的内容非常有用,也可能在电视上播放。 但是,无法使用默认 DMO 包装器保留交错,因为该筛选器在其输入样本上不支持 INSSBuffer

DMO 使用该接口获取它接收的每个样本的交错设置。 如果未找到接口,则与 DMO 包装器一样,DMO 只是将输入样本视为非隔行。 若要在 DirectShow 中执行隔行编码,有几种替代方法。 最简单的方法可能是直接使用 Windows Media Format 9 系列 SDK 或使用 WM ASF 编写器 DirectShow 筛选器来创建交错 ASF 文件。 然后,可以将该文件转码为其他格式。 如果转码为 AVI,将具有交错文件,但标准 DirectShow AVI 播放筛选器无法识别它,因为它们不支持 VIDEOINFOHEADER2。 另一种方法是编写自己的支持 INSSBuffer 接口的 DMO 包装器筛选器。

使用编解码器 DME