在 AVStream 编解码器中支持动态格式更改

当正在运行的媒体流中发生动态格式更改时,系统提供的 Devproxy 模块将与捕获引脚协商,以确定新格式是否可接受。

当动态格式更改源自媒体源时,将发生以下事件序列:

  1. 驱动程序收到 KSPROPERTY_CONNECTION_PROPOSEDATAFORMAT 请求,以确定输入 KS 引脚是否支持新媒体类型。 驱动程序必须支持此属性。

  2. 如果输入引脚支持新媒体类型,则KSPROPERTY_CONNECTION_PROPOSEDATAFORMAT处理程序应返回STATUS_SUCCESS。 然后,驱动程序确定是否可以通过将建议的输入与当前所选的输出媒体类型一起使用来恢复流。 如果是,则继续流。

  3. 如果输入引脚不支持新建议的媒体类型,KSPROPERTY_CONNECTION_PROPOSEDATAFORMAT处理程序应返回错误。 然后,HW MFT 使用连接的组件重新协商媒体类型。

  4. 如果输入引脚支持新媒体输入类型,但 KS 筛选器需要其他输出媒体类型,则驱动程序应生成 KSEVENT_DYNAMIC_FORMAT_CHANGE 事件(如本主题后面部分所述)以通知 HW MFT 媒体类型更改。

  5. 当 HW MFT 收到 KSEVENT 通知时,它会将输出引脚从 KSSTATE_RUN 转换为KSSTATE_STOP。

  6. 然后,HW MFT 查询驱动程序中的可用媒体类型,这转换为对驱动程序的 AVStrMiniIntersectHandlerEx 交集处理程序的调用。 驱动程序应按优先顺序报告首选输出媒体类型。

  7. 用户模式客户端选择媒体类型,并在 HW MFT 的输出引脚上设置新媒体类型。 这会导致调用驱动程序的 AVStrMiniPinSetDataFormat 调度例程。 如果驱动程序通过返回STATUS_SUCCESS接受格式,则使用新媒体类型继续流式处理。 如果调用失败,格式更改所涉及的组件必须重新协商媒体类型。

  8. HW MFT 会检查连接的媒体中是否有任何更改。 如果没有更改,它会在引脚上设置所选媒体类型,并将其放入KSSTATE_RUN。 如果连接的介质发生更改,则 HW MFT 会销毁引脚,并使用新选择的媒体类型和介质重新创建引脚。 然后,MFT 将引脚放入KSSTATE_RUN。

  9. 流式处理恢复。

在某些情况下,媒体源可能无法检测到格式更改。 例如,MPEG2 解码器必须解码每个数据包才能找到任何格式更改。

在这种情况下,如果驱动程序检测到格式更改,则硬件驱动程序应生成动态格式更改 KSEVENT。 然后,HW MFT 会查询其支持的媒体类型的固定。 引脚应按优先顺序返回首选媒体类型。 然后,HW MFT 遵循上一部分的步骤 4 到 9 中所述的事件序列。

如果驱动程序无法处理此类格式更改,则应返回流式处理错误,该错误随后将传播到 MF。

下面的代码示例演示如何使用 KSEVENT 定义新的动态格式更改:

// {162AC456-83D7-4239-96DF-C75FFA138BC6}
#define STATIC_KSEVENTSETID_DynamicFormatChange\
    0x162ac456, 0x83d7, 0x4239, 0x96, 0xdf, 0xc7, 0x5f, 0xfa, 0x13, 0x8b, 0xc6 DEFINE_GUIDSTRUCT("162AC456-83D7-4239-96DF-C75FFA138BC6", KSEVENTSETID_ DynamicFormatChange);
#define KSEVENTSETID_DynamicFormatChange DEFINE_GUIDNAMED(KSEVENTSETID_ DynamicFormatChange)

typedef enum {
KSEVENT_DYNAMIC_FORMAT_CHANGE = 0
};

DEFINE_KSEVENT_TABLE(DynamicFormatChangeEventTable) {
    DEFINE_KSEVENT_ITEM
    (
        KSEVENT_DYNAMIC_FORMAT_CHANGE,
        sizeof(KSEVENTDATA),
        0,   
        NULL,
        NULL,
        NULL
    )
};

KSEVENT_SET PinEventTable[] =
{
    DEFINE_KSEVENT_SET
    (
        &KSEVENTSETID_DynamicFormatChange,
        SIZEOF_ARRAY(DynamicFormatChangeEventTable),
        DynamicFormatChangeEventTable
    )
};

每个引脚都应在其引脚描述符中公开此事件。 事件的类型为 KSEVENTF_EVENT_HANDLE。

在驱动程序生成此事件之前,它应根据当前所选的输入媒体类型为 KS 引脚设置首选媒体类型。 可以通过在引脚的描述符上使用 _KsEdit 函数来执行此操作。

若要生成事件,驱动程序应调用 KsGenerateEvents