处理流更改

本主题介绍媒体基础转换 (MFT) 在流式处理期间应如何处理格式更改。

重要

本主题不适用于编码器。 编码器不应传播本主题中所述的格式更改。 编码器应仅接受与当前配置的输出类型匹配的输入类型。

 

格式更改概述

通常,格式在流式处理期间可能会更改的原因有两个。

  • 客户端可能会切换到具有新格式的流。 例如,在数字电视中,这可能是由于频道更改而发生的。
  • 在某些视频格式(如 H.264)中,位流可以发出格式更改信号。 此类更改可能包括字段优势、视频分辨率或像素纵横比的更改。

如果编码类型发生更改,客户端可能需要从管道中删除 MFT 并将其替换为另一个 MFT。 (例如,客户端可能需要交换新的 decoder.) 本主题不介绍这种情况。 本主题仅介绍当前 MFT 可以处理新格式的情况。

如果格式发生更改,MFT 可能需要新的输入类型、新的输出类型或两者。

  • 对输入类型的更改由客户端启动。 MFT 永远不会更改其自己的输入类型。
  • 对输出类型的更改由 MFT 启动。 MFT 指示它需要新的输出类型,客户端会与 MFT 协商新的输出类型。

因此,可能存在三种不同的情况:

  • 客户端设置新的输入类型。 MFT 使用新格式,不更改其输出类型。
  • 客户端设置新的输入类型,这会触发输出类型的更改。
  • 输入类型不会更改,但 MFT 会检测位流中的格式更改,这需要新的输出类型。

实现格式更改

本主题的其余部分介绍了客户端应如何处理格式更改,以及如何在 MFT 中实现格式更改。

输出类型

任何 MFT 都可以启动对其输出类型的更改,如下所示:

  1. 客户端调用 IMFTransform::P rocessOutput。 MFT 的响应如下所示:
    1. MFT 不会在 ProcessOutput 中生成输出示例。
    2. MFT 在 MFT_OUTPUT_DATA_BUFFER 结构的 dwStatus 成员中设置 MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE 标志。
    3. ProcessOutput 方法MF_E_TRANSFORM_STREAM_CHANGE返回错误代码。
  2. 客户端调用 IMFTransform::GetOutputAvailableType。 此方法返回一组更新的输出类型。
  3. 客户端调用 SetOutputType 来设置新的输出类型。
  4. 客户端继续调用 ProcessInput/ProcessOutput

输入类型

对输入类型的更改由客户端启动,从不由 MFT 启动。 如果输入类型发生更改,可能会触发对输出类型的更改。

事件的确切序列取决于 MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE 属性的值。

说明
FALSE 在客户端设置新的输入类型之前,它必须清空 MFT。
TRUE 客户端可以设置新的输入类型,而无需耗尽 MFT。

 

MFT 通过其 IMFTransform::GetAttributes 方法公开此属性。 此属性的默认值为 FALSE;如果 MFT 未设置 属性,则将该值视为 FALSE

MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE为 FALSE

  1. 客户端发送 MFT_MESSAGE_COMMAND_DRAIN 消息。
  2. 客户端通过调用 IMFTransform::P rocessOutput 来排出 MFT,直到 ProcessOutput 返回 MF_E_TRANSFORM_NEED_MORE_INPUT
  3. 客户端调用 IMFTransform::SetInputType 来设置新的输入类型。
  4. MFT 验证输入类型。 如果该类型无效, SetInputType 将返回 MF_E_INVALIDMEDIATYPE 或其他错误代码。 否则, SetInputType 返回S_OK。
  5. 假设输入类型有效,MFT 将评估输出类型是否也发生更改。 否则,流式处理将继续进行,无需进一步操作。
  6. 如果输出类型发生更改:
    1. MFT 会使其当前输出媒体类型失效,并更新可用输出媒体类型的列表。
    2. 下一次调用 ProcessOutput 将返回 MF_E_TRANSFORM_STREAM_CHANGE,如上一部分所述。
    3. 客户端调用 IMFTransform::GetOutputAvailableType 以获取输出类型的更新列表。
    4. 客户端调用 SetOutputType

MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE为 TRUE

  1. 客户端调用 IMFTransform::SetInputType 来设置新的输入类型。
  2. MFT 验证输入类型。 如果该类型无效, SetInputType 将返回 MF_E_INVALIDMEDIATYPE 或其他错误代码。 否则, SetInputType 返回S_OK。
  3. 假设输入类型有效,MFT 将评估输出类型是否也发生更改。 否则,流式处理将继续进行,无需进一步操作。
  4. 在输出类型更改之前,MFT 必须处理任何缓存的输入示例,如下所示:
    1. MFT 不会使其当前输出类型失效。
    2. MFT 从缓存的输入样本中生成尽可能多的输出。
    3. MFT 在处理缓存样本时是否接受新的输入样本是可选的。 如果是这样,新的输入示例将使用新的输入格式,因此 MFT 必须跟踪格式更改时的点。
  5. MFT 处理在输入类型更改之前收到的所有样本后, IMFTransform::P rocessOutput 将返回 MF_E_TRANSFORM_STREAM_CHANGE
  6. MFT 会使其当前输出类型失效,并更新可用输出媒体类型的列表。
  7. 客户端协商新的输出类型,如前所述。

异步 MCT 必须为 MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE 属性返回值 TRUE。 使用异步 MFT 时,客户端可以假定 MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE 属性设置为 TRUE

MFT_SUPPORT_DYNAMIC_FORMAT_CHANGETRUE 时,main区别在于,在设置新的输入类型之前,客户端不需要清空 MFT。 因此,当 MFT 保留输入样本时,输入类型可能会更改。 重要的是,MFT 不会简单地删除这些样本。 此外,在 MFT 处理其所有缓存数据之前,输出类型无法更改。

上一段特别适用于视频解码器,这些解码器可以按临时顺序接收编码间帧,因此需要缓存它们。 如果 MFT 不缓存输入样本,则清空本质上是一种无操作。 在这种情况下,MFT 可以将 MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE 设置为 FALSE (,或者将属性保留为未设置) 。

另请注意,每个 MFT 都应在排空后正确处理格式更改。 MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE 属性指示 MFT 是否支持格式更改而不排空。

交错模式下的更改

视频交错模式中的更改是一种特殊情况,因为它们不会使当前媒体类型失效。 而是通过设置媒体示例的属性为每个视频帧指定交错模式。 视频 MFT 应检查每个输入示例,以了解是否存在这些标志。

当场优势从上场切换到下场时,或者视频在逐行图和隔行图之间切换时,隔行模式可能会更改。

有关详细信息,请参阅 示例上的交错标志

编写自定义 MFT