ASF 媒体源

Media Foundation 提供 ASF 媒体源,应用程序可用于在体系结构的管道层中表示 ASF 文件。

为了播放 ASF 文件,应用程序可以使用 ASF 媒体源将数据馈送到播放管道中。 在编码方案中,应用程序可以使用 ASF 媒体源作为源转换为其他格式,或者将更高的比特率文件转换为较低的比特率文件,而无需更改格式。 ASF 媒体源必须在管道层中使用,即应用程序必须使用媒体会话来控制操作。 此级别的访问允许应用程序在媒体会话正在进行时获取事件。 若要获取对 ASF 内容的较低级别的访问,应用程序必须使用 WMContainer 层 ASF 组件。

ASF 媒体源实现 IMFMediaSource 接口,该接口是 Media Foundation 中媒体源的通用接口。 与任何其他媒体源一样,ASF 媒体源提供主要描述 ASF 标头对象的演示文稿描述符。 此外,ASF 媒体源还提供表示媒体内容中每个流的流描述符。 有关详细信息,请参阅 ASF 文件结构

创建 ASF 媒体源

若要创建 ASF 媒体源,应用程序必须使用 源解析程序。 若要创建 ASF 媒体源,应用程序必须提供源解析程序为其创建 ASF 媒体源的源。 源信息必须通过指定源文件的 URL 或包含媒体的字节流来提供。 如果应用程序通过指定 URL 选择创建 ASF 媒体源,则必须调用 IMFSourceResolver::CreateObjectFromURL 进行同步操作或 IMFSourceResolver::Begin...用于异步操作的 EndCreateObjectFromURL 。 从字节流创建媒体源的过程类似。 应用程序必须调用 IMFSourceResolver::CreateObjectFromByteStream 进行同步操作,或者 IMFSourceResolver::Begin...用于异步操作的 EndCreateObjectFromBytestream 。 这些调用必须在 dwFlags 参数中指定MF_RESOLUTION_MEDIASOURCE。 有关使用此标志的详细信息,请参阅“使用源解析程序”。

如果应用程序为本地文件指定 URL,则 URL 字符串可以包含媒体文件的路径,也可以以“文件:”方案作为前缀。 文件扩展名必须为“.asf”、“.wm”、“L”.wma“或”.wmv”。 对于网络上的 ASF 文件,源解析程序会创建使用 ASF 媒体源 的网络源

在对象创建过程中,源解析程序在系统注册表中查找方案处理程序和字节流处理程序的列表,并加载最接近的匹配处理程序,该处理程序可以分析媒体内容,并创建下面的媒体源对象。 无论用于创建媒体源 (URL 和字节流) 的方法如何,源解析程序创建字节流并将源媒体的内容读取到字节流中。 有关详细信息,请参阅 方案处理程序和Byte-Stream处理程序

有关如何创建媒体源的代码示例,请参阅 “使用源解析程序”。

ASF 媒体源的配置设置

源解析程序查询基础字节流的功能,并确定新创建的媒体源上允许这些操作。 其中一项功能正在寻求。 如果允许查找操作,应用程序可以在寻求演示文稿中的特定点时指定媒体源使用的查找模式。

应用程序可以在创建对象期间设置要使用的媒体源的查找模式。 使用指定的查找模式创建 ASF 媒体源后,无法在媒体源上修改它或在演示文稿期间动态更改。 查找首选项被指定为应用程序调用中用于创建媒体源的相关源解析程序方法的属性。 这些属性集在属性存储中设置,并传递给 pProps 参数。 如果未传递这些属性,则媒体源会使用默认设置。 有关设置这些属性的详细信息,请参阅 配置媒体源

如果允许查找,ASF 媒体源支持以下搜寻模式:

  • 精确查找:在此模式下,ASF 媒体源依赖于 ASF 文件的 ASF 索引对象。 如果文件没有索引对象,则会禁用精确查找,使用其他模式之一,具体取决于媒体源上设置的应用程序指定的属性。
  • 近似查找:应用程序通过将属性存储中的 MFPKEY_ASFMediaSource_ApproxSeek 传递给相关的源解析程序方法来请求此模式。 但是,仅当字节流不支持基于时间的查找时,才使用近似查找。 在此模式下,媒体源确定相对接近搜寻时间的开始时间。 如果 ASF 文件包含 ASF 索引对象,则用于计算开始时间。 近似查找不太准确,但比精确查找更快,因为在预先确定的开始时间呈现第一个样本的时间更快。
  • 迭代查找:若要设置此模式,应用程序必须设置 MFPKEY_ASFMediaSource_IterativeSeekIfNoIndex 属性。 迭代查找是一种算法,用于在不包含 ASF 索引对象的 ASF 文件中查找位置。 在此模式下,媒体源通过读取字节流偏移量来确定搜寻点的粗略估计值。 它使用一系列近似值(基于平均比特率)逐渐接近目标查找时间。 (算法类似于二进制搜索。) 迭代查找比使用索引对象查找的时间长,因此默认禁用该算法。 如果设置此属性,请使用以下属性设置搜索参数:MFPKEY_ASFMediaSource_IterativeSeek_Max_CountMFPKEY_ASFMediaSource_IterativeSeek_Tolerance_In_MilliSecond。 这些属性分别设置迭代的最大次数和容差。 算法在达到最大迭代数时或查找与查找时间距离在指定容错范围内的数据包时停止。

简言之,应用程序可以选择在 ASF 文件不包含 ASF 索引对象时选择近似或迭代查找。

ASF 媒体源对象模型

ASF 媒体源实现 IMFMediaSource 接口并公开以下接口。 应用程序可以通过在 ASF 媒体源上调用 IMFMediaSource::QueryInterface 来获取对这些接口的引用。

接口 说明
IMFMediaSource 所有媒体源都是必需的。
IMFMediaEventGenerator 所有媒体源都是必需的。 允许应用程序通过媒体会话从媒体源获取事件。
IMFGetService 查询指定服务接口的媒体源。
IPropertyStore 设置和获取媒体源的属性。 每个属性都包含一个描述性名称和一个值。
IMFMetadata 描述 ASF 文件的元数据。
IMFMetadataProvider 检索整个演示文稿的元数据集合,或检索演示文稿中的一个流。
IMFRateSupport 查询支持的播放速率范围,包括反向播放。
IMFRateControl 获取或设置播放速率。
IMFTrustedInput 获取源中包含的每个 ASF 流的 ITA。
IMFPMPClient 使媒体源能够接收指向 IMFPMPHost 接口的指针,该接口用于在 PMP 进程中创建对象。
IMFTimecodeTranslate 在电影协会和电视工程师协会之间转换 (SMPTE) 时间代码和 100 纳米秒的时间单位。

 

ASF 媒体源服务

ASF 媒体源提供适用于 ASF 文件的各种服务。 若要获取指向特定服务的指针,应用程序必须在对 MFGetService 的调用中使用以下服务标识符之一。 有关详细信息,请参阅 服务接口

服务标识符 说明
MF_RATE_CONTROL_SERVICE 通过使用此标识符,应用程序可以获取指向 IMFRateSupportIMFRateControl 接口的指针。 通过使用媒体源实现的速率支持对象,应用程序可以检查基础 ASF 媒体文件是否支持特定速率,也可获得最快和最慢的速率。 通过使用速率控制对象,应用程序可以获取和设置播放速率。 如果应用程序指定了用于播放的特定速率,ASF 媒体源首先检查所请求的速率是否在速率限制范围内, (由快速速率和速度最慢) 确定,然后设置速率。 这不会检查可变条件,因为比特率可能会更改任何时刻,具体取决于网络带宽。 有关详细信息, 速率控制
MF_METADATA_PROVIDER_SERVICE 通过使用此标识符,应用程序可以获取指向 ASF 媒体源 的 IMFMetadataProvider 接口的指针。 此接口提供对 ASF 文件的信息的访问,具体访问 ASF 标头对象以及媒体内容中包含的流。 标头信息通过演示文稿描述符属性公开,流信息通过流描述符属性提供。 有关这些属性的详细信息,请参阅 ASF 标头对象的 Media Foundation 属性。 除了通过属性公开的信息外,还存在描述性元数据,这些元数据设置为属性。
MF_PROPERTY_HANDLER_SERVICE 通过使用此标识符,应用程序可以获取指向 ASF 媒体源 的 IPropertyStore 接口的指针。 属性存储包含与 ASF 文件相关的所有元数据。 此标识符是 Windows 7 中的新增标识符,用于获取元数据属性MF_METADATA_PROVIDER_SERVICE。
MFNETSOURCE_STATISTICS_SERVICE 有关详细信息,请参阅 在客户端日志记录中检索网络统计信息。
MF_TIMECODE_SERVICE 通过使用此标识符,应用程序可以获取指向媒体源的 IMFTimecodeTranslate 接口的指针。 此实现可用于执行时间代码转换,例如将 SMPTE 时间代码转换为 100 nano 秒单位和后退。

 

Timecode 翻译

ASF 媒体源提供时间代码翻译服务,使应用程序能够将 SMPTE 时间代码转换为 100 纳秒单元中最接近的演示时间 () 。 相反,应用程序还可以获取请求的演示时间的时间代码。 该服务通过 ASF 媒体源实现的 IMFTimecodeTranslate 接口提供。 此接口指针上的方法调用是异步的,可以从主应用程序线程运行,而不会阻止应用程序的用户界面。

以下步骤汇总了时间代码转换的过程:

  1. 通过调用 MFGetService 并指定MF_TIMECODE_SERVICE标识符,获取指向 ASF 媒体源的 IMFTimecodeTranslate 接口的指针。
  2. 调用 IMFTimecodeTranslate::BeginConvertTimecodeToHNSIMFTimecodeTranslate::BeginConvertHNSToTimecode ,并指定要翻译的时间。 对于 BeginConvertTimecodeToHNS,时间代码必须指定为具有VT_I8数据类型的 PROPVARIANT 变量。 BeginConvertHNSToTimecode 方法要求以 100 纳秒为单位的时间作为 MFTIME 类型。
  3. 通过适当调用 IMFTimecodeTranslate::EndConvertTimecodeToHNSIMFTimecodeTranslate::EndConvertTimecodeToHNS 来完成异步操作。

在创建媒体源期间,源解析程序为媒体源读取 ASF 内容的文件创建字节流。 为了使时间转换成功,与 ASF 文件关联的字节流必须具有查找功能:否则,应用程序从 Begin... 调用中获取MF_E_BYTESTREAM_NOT_SEEKABLE错误。 时间转换的另一个要求是 ASF 文件(由 ASF 媒体源表示)必须具有 ASF 索引对象。 演示时间和时间代码是从 ASF 索引对象中提取的,这些对象维护所有索引和 ASF 文件的相应查找点。 对于演示时代码转换,ASF 文件必须包含简单索引对象;对于时间代码到演示文稿的时间转换,ASF 文件必须具有索引对象。 转换操作依赖于基础 索引器 (WMContainer 组件) 来分析和读取与 ASF 文件关联的索引对象。 如果文件不包含索引对象,则应用程序异步接收MF_E_NO_INDEX错误代码。

若要转换应用程序请求的时间,媒体源会枚举文件中的流,并查找包含相应 ASF 索引对象的流。 如果找到此类流,媒体源将分析流的 ASF 数据包,直到达到正确的时间代码。 找到正确的示例后,它会从示例中检索相应的呈现时间或时间代码,并将其返回到调用方。

脚本命令支持

生成包含脚本流的 ASF 拓扑时,脚本流节点将添加到拓扑中。 此节点将在适当的时间发送 IMFSamples。 脚本源节点提供的 IMFSample 将数据存储在与示例关联的 IMFMediaBuffer 中。 可以在示例中调用 CopyToBuffer 以获取 IMFMediaBuffer,然后在缓冲区上调用 Lock 以获取数据。

脚本流有效负载以类型字符串的形式打包到缓冲区中,后跟 NULL,后跟命令字符串,后跟 NULL。 字符串采用 ASF 格式的 Unicode。

例如,有效负载可能类似于以下 (,其中 \0 指示 NULL 字符) :

URL\0http://contoso.com\0

Text\0This is a caption\0

管道层 ASF 组件

媒体基础中的 ASF 支持