使用第三方编解码器创建 ASF 文件

可以使用Windows媒体格式 SDK 创建包含使用所选任何编解码器编码的数字媒体的 ASF 文件。 使用此 SDK 附带的编解码器时,必须执行以下步骤。

  1. 使用所需的编解码器对内容进行编码。
  2. 查找或创建 GUID 值,以标识使用步骤 1 中使用的编解码器编码的内容。
  3. 创建新的配置文件,或修改现有配置文件以用于编码的内容。
    • 为具有适当主要类型的编码内容创建流。 有关主要媒体类型的详细信息,请参阅 媒体类型。 使用步骤 2 中标识的 GUID 作为媒体子类型。
    • 将流的比特率和缓冲区窗口设置为不会导致缓冲区溢出的值。 应在编码时从编解码器中获取这些值。 SDK 运行时组件检查比特率/缓冲区窗口值,并在必要时删除样本,使给定的数据适合这些值。 如果设置的值不正确,则文件不会正确流式传输,从而导致播放不佳。
    • 对于视频流,必须将 WMVIDEOINFOHEADER 结构中包含的 BITMAPINFOHEADER 结构的 biCompression 成员设置为内容的相应 FOURCC 值。 此值必须等于子类型 GUID 的前四个字节。 例如,如果 biCompression 为 MAKEFOURCC ('T','E','S','T') =0x54455354,则子类型 GUID 将如下所示:54455354-XXXX-XXXX-XXXX-XXXXXXXXXXXXXXX。
  4. 创建编写器对象并加载在上一步中创建的配置文件。 有关写入文件的详细信息,请参阅 写入 ASF 文件
  5. Loop文件输入,并像平常一样为每个文件分配输入属性。 有关输入的详细信息,请参阅 “使用输入”。 对于使用第三方编解码器编码的流,在调用 IWMWriter::BeginWriting 之前,将 IWMInputMediaProps 接口指针设置为 NULL
  6. 使用在上一步中创建的新配置文件写入文件。 使用 IWMWriterAdvanced::WriteStreamSample 而不是 IWMWriter::WriteSample 传递压缩的示例。 对于视频,必须通过将WM_SF_CLEANPOINT作为 dwFlags 参数传递来指定哪些示例是关键帧。

若要处理和解压缩使用第三方编解码器编码的流,必须读取压缩的流示例。 读取应用程序还必须处理流的示例解压缩。

将 MPEG-2 流放入 ASF

注意

本主题适用于使用 Windows 媒体格式 SDK 将 MPEG-2 (或其他使用 B 帧) 压缩格式的应用程序放入 ASF 文件容器。

 

编写器对象要求所有输入样本都有时间戳,并且假定每个输入样本的呈现时间晚于前面。 虽然几乎所有未压缩的视频,甚至一些压缩的视频流都满足这些条件,但 MPEG-2 流不会。 在 MPEG-2 中,并非所有样本都带有时间戳,并且 B 帧存在时,样本解码顺序与呈现顺序不同。 当编写器对象遇到无序样本时,它会将它们重新排列为“正确”顺序。 因此,若要在 ASF 容器中本机存储 MPEG-2 流, (未解码) ,必须执行以下步骤:

写入文件时:

  1. 将固定大小的数据单元扩展 (DUE) 添加到每个输入示例,该示例包含实际 MPEG 时间戳开始时间和停止时间值的结构。 如果示例没有时间戳,请使用 -1 表示这些值。
  2. 为编写器对象提供始终增加的“虚拟”输入时间戳,以便以与收到的样本完全相同的顺序将示例写入文件。 虚拟时间戳应大致对应于实际呈现时间,随着时间的推移平均。 虚拟时间戳将形成查找时间线,因此,如果它们相对于实时时间戳进行分流,则对文件执行查找操作将产生意外的结果。 但是,样本时间之间的抖动量有限不会严重影响搜寻操作。

读取文件时:

  • 对于从文件读取的每个示例,请检查 DUE。 如果它包含大于或等于零的开始时间,请将该值复制到输出示例的时间戳,然后再将其传递到解码器。 将输出样本上所有其他时间戳设置为 NULL。 在DirectShow中,通过调用 IMediaSample::SetTime (NULLNULL) 来完成此操作。

缓冲内容

IWMWriter 接口

IWMWriterAdvanced 接口

使用异步读取器传递压缩示例

使用同步读取器检索流样本

WMVIDEOINFOHEADER

使用配置文件

编写 ASF 文件