处理 DMO 中的数据
[与此页面关联的功能 DirectShow 是旧版功能。 它已被 MediaPlayer、 IMFMediaEngine 和 Media Foundation 中的音频/视频捕获所取代。 这些功能已针对Windows 10和Windows 11进行了优化。 Microsoft 强烈建议新代码尽可能在 Media Foundation 中使用 MediaPlayer、 IMFMediaEngine 和 音频/视频捕获 ,而不是 DirectShow。 如果可能,Microsoft 建议重写使用旧 API 的现有代码以使用新 API。]
本部分介绍如何使用 DMO 处理数据流。 本部分中列出的步骤是默认行为;所有 DTO 都必须支持此处所述的方法。 这些方法对输入和输出使用单独的缓冲区。 某些 DTO 还支持使用单个缓冲区的就地处理。 有关就地处理的详细信息,请参阅 就地处理。
分配缓冲区
客户端负责所有缓冲区分配。 在 DMO 上设置媒体类型后,向 DMO 查询每个流的缓冲区要求。 这些可能会根据媒体类型而更改。 对于每个流,调用 IMediaObject::GetInputSizeInfo 或 IMediaObject::GetOutputSizeInfo 方法。 这些方法返回以下信息:
- 最小缓冲区大小(以字节为单位)。
- 对齐要求(如果有)。 如果起始地址是某个指定整数的倍数,则会对齐缓冲区。
- DMO 将保留用于查找的最大数据量。 此数字仅适用于输入流。 对于某些类型的数据 (例如 MPEG 编码) ,DMO 可能需要在流中向前看。 lookahead 值指示 DMO 在生成输出之前需要多少输入数据。
客户端必须分配符合这些要求的缓冲区。 此外,DMO 可能对客户端如何打包输入数据有要求。 例如,DMO 可能要求每个缓冲区仅包含一个示例 (或视频帧) 。 若要确定这些要求,请调用 IMediaObject::GetInputStreamInfo 方法。 IMediaObject::GetOutputStreamInfo 方法返回有关输出流的类似信息。
在默认流式处理模型中,客户端不会将原始缓冲区指针传递给 DMO。 相反,它使用公开 IMediaBuffer 接口的轻型 COM 对象。 IMediaBuffer 接口充当内存块的 COM 包装器。 因为它是 COM 对象,因此支持引用计数,这有助于确保缓冲区在仍在使用时不会释放。
注意
IMediaBuffer 接口提供类似于 DirectShow 中的 IMediaSample 接口的函数。
客户端必须实现 IMediaBuffer 对象。 有关详细信息,请参阅 实现 IMediaBuffer。
处理数据
若要处理数据,请执行以下操作:
- 对于每个输入流,使用输入数据填充缓冲区。
- 调用 IMediaObject::P rocessInput 传递每个缓冲区。
- 调用 IMediaObject::P rocessOutput 来处理数据。 此方法采用缓冲区数组,每个输出流各一个。
- 重复此操作,直到没有更多的输入数据。
ProcessInput 方法一次接受一个流的输入。 通常, 方法会立即返回,并且 DMO 保留 IMediaBuffer 对象的引用计数。 它在处理缓冲区中的所有数据后,或者当应用程序刷新 DMO 时释放对象。 在 DMO 释放缓冲区之前,请勿重复使用缓冲区。 若要确定输入流是否可以接受更多数据,请调用 IMediaObject::GetInputStatus 方法。 如果流可以接受更多输入,此方法将返回DMO_INPUT_STATUSF_ACCEPT_DATA标志。
ProcessOutput 方法一次为所有输出流生成输出。 应用程序传入 DMO_OUTPUT_DATA_BUFFER 结构的数组,每个输出流一个结构。 数组中的每个结构都有一个指向 IMediaBuffer 对象的指针。 DMO 将尽可能多的输出数据写入缓冲区。 它还设置各种标志来报告操作的状态。 DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE标志指示 DMO 可以从现有输入生成更多输出。 在这种情况下,客户端可以再次调用 ProcessOutput 。 否则,它应使用更多输入数据调用 ProcessInput 。 DMO 永远不会修改输入缓冲区中的数据;它只写入输出缓冲区。
将所有数据传递到输入流后,调用 IMediaObject::D iscontinuity 方法。 在处理剩余输出 (或刷新 DMO) 之前,DMO 不接受该流的进一步输入。
在流式传输开始后的任何时候,DMO 都可以接收输入或生成输出,或者同时接收两者。 因此, GetInputStatus 返回DMO_INPUT_STATUSF_ACCEPT_DATA,或 ProcessOutput 返回DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE。 应用程序通过测试这些标志并相应地调用 ProcessInput 或 ProcessOutput 来保持数据流。 若要中断数据流,请调用 IMediaObject::Flush 方法。 此方法导致 DMO 放弃它在内部保存的任何缓冲区。
相关主题