DirectShow 中的数据流概述

[与此页面关联的功能 DirectShow 是一项旧功能。 它已被 MediaPlayerIMFMediaEngine媒体基金会中的音频/视频捕获取代。 这些功能已针对Windows 10和Windows 11进行了优化。 Microsoft 强烈建议新代码尽可能使用 MediaPlayerIMFMediaEngineMedia Foundation 中的音频/视频捕获 ,而不是 DirectShow。 如果可能,Microsoft 建议重写使用旧 API 的现有代码以使用新 API。]

本部分全面概述了 DirectShow 中数据流的工作原理。 有关详细信息,请参阅文档的其他部分。

数据保存在缓冲区中,缓冲区只是字节数组。 每个缓冲区由名为 媒体示例的 COM 对象包装,该对象实现 IMediaSample 接口。 示例由另一种类型的对象(称为分配器)创建,该对象实现 IMemAllocator 接口。 虽然两个或更多个引脚连接可能共享同一分配器,但为每个引脚连接分配一个分配器。 下图演示了此过程。

缓冲区、样本和分配器

每个分配器创建媒体样本池,并为每个样本分配缓冲区。 每当筛选器需要使用数据填充缓冲区时,它都会通过调用 IMemAllocator::GetBuffer 从分配器请求样本。 如果分配器具有其他筛选器当前未使用的任何样本, GetBuffer 方法将立即返回,并返回指向样本的指针。 如果分配器的所有样本都在使用中,则 方法将阻止,直到样本可用。 当 方法返回样本时,筛选器会将数据放入缓冲区,在示例 (设置相应的标志,通常包括时间戳) ,并将示例传送到下游。

当呈现器筛选器收到样本时,它会检查时间戳并保留样本,直到筛选器图的引用时钟指示应呈现数据。 筛选器呈现数据后,会释放示例。 在样本的引用计数为零之前,样本不会返回到分配器的样本池中,这意味着每个筛选器都释放了样本。 下图演示了此过程。

正在等待免费媒体示例的解码器

上游筛选器可能在呈现器之前运行,也就是说,它填充缓冲区的速度可能比呈现器使用缓冲区快。 即便如此,样本也不会提前呈现,因为呈现器会保留每个样本,直到其呈现时间为止。 此外,上游筛选器不会意外覆盖缓冲区,因为 GetSample 仅返回未使用的示例。 上游筛选器可以提前运行的数量取决于分配器池中的样本数。

上图仅显示一个分配器,但通常每个流有多个分配器。 因此,当呈现器释放示例时,它可以具有级联效果。 下图显示了解码器在等待呈现器释放示例时保存压缩的视频帧的情况。 分析器筛选器也在等待解码器发布示例。

等待样本的两个筛选器

当呈现器释放其示例时,解码器对 GetBuffer 的挂起调用将返回。 然后,解码器可以解码压缩的视频帧并释放它所持有的样本,从而解除阻止分析程序挂起的 GetBuffer 调用。

筛选器图中的数据流