筛选状态

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

筛选器有三种可能的状态:已停止、暂停和正在运行。 暂停状态的目的是在图中提示数据,以便运行命令立即响应。 筛选器关系图管理器控制所有状态转换。 当应用程序调用 IMediaControl::RunIMediaControl::P auseIMediaControl::Stop 时,Filter Graph 管理器对所有筛选器调用相应的 IMediaFilter 方法。 停止和运行之间的转换始终会经历暂停状态,因此,如果应用程序在已停止的图形上调用 “运行 ”,筛选器图形管理器会在运行图形之前暂停图形。

对于大多数筛选器,正在运行和暂停状态是相同的。 请考虑以下筛选器图:

源 > 转换 > 呈现器

现在假设源筛选器不是实时捕获源。 当源筛选器暂停时,它会创建一个线程来生成新数据,并尽快将其写入媒体样本。 线程通过在转换筛选器的输入引脚上调用 IMemInputPin::Receive 将示例“推送”到下游。 转换筛选器接收源筛选器线程上的样本。 它可以使用工作线程将样本传送到呈现器,但通常在同一线程上传递样本。 呈现器暂停时,它会等待接收样本。 收到一个样本后,它会无限期阻止并保留该样本。 如果是视频呈现器,则会将示例显示为海报图像,并根据需要重新绘制图像。

此时,流已完全提示并准备好呈现。 如果图形保持暂停状态,示例将“堆积”在第一个样本后面的图形中,直到 ReceiveIMemAllocator::GetBuffer 中阻止每个筛选器。 不过,不会丢失任何数据。 取消阻止源线程后,它只会从阻止的点恢复。

源筛选器和转换筛选器忽略从暂停到正在运行的转换,它们只是继续尽可能快地处理数据。 但是,当呈现器运行时,它将开始呈现示例。 首先,它呈现暂停时保存的示例。 然后,每次收到新样本时,它都会计算样本的呈现时间。 (有关详细信息,请参阅 DirectShow 中的时间和时钟。) 呈现器将保留每个样本,直到呈现时间,此时呈现示例。 在等待演示时间时,它会在 Receive 方法中阻止,或者接收具有队列的工作线程上的新示例。 来自呈现器上游的筛选器不涉及计划。

实时源(如捕获设备)是此常规体系结构的例外。 使用实时源时,不宜提前提示任何数据。 应用程序可能会暂停图形,然后等待很长时间后再运行它。 图形不应呈现“过时”样本。 因此,实时源在暂停时不生成任何样本,仅在运行时生成。 为了向筛选器关系图管理器发出这一事实信号,源筛选器的 IMediaFilter::GetState 方法返回VFW_S_CANT_CUE。 此返回代码指示筛选器已切换到暂停状态,即使呈现器未收到任何数据。

当筛选器停止时,它会拒绝传递给它的任何更多样本。 源筛选器关闭其流式处理线程,其他筛选器关闭它们可能已创建的任何工作线程。 引脚取消提交其分配器。

状态转换

筛选器关系图管理器按上游顺序执行所有状态转换,从呈现器开始,然后向后工作到源筛选器。 必须进行此排序,以防止删除样本并防止图形死锁。 最重要的状态转换是在暂停和停止之间转换:

  • 已停止以暂停:当每个筛选器暂停时,它便准备好从下一个筛选器接收样本。 源筛选器是最后一个暂停的筛选器。 它创建流式处理线程并开始传送示例。 由于所有下游筛选器都已暂停,因此没有筛选器会拒绝任何样本。 筛选器图形管理器不会完成转换,直到图形中的每个呈现器都收到示例 ((实时源除外),如前面) 所述。
  • 暂停以停止:当筛选器停止时,它会释放它保存的任何样本,从而取消阻止在 GetBuffer 中等待的任何上游筛选器。 如果筛选器正在等待 Receive 方法中的资源,它将停止等待并从 Receive 返回,这会取消阻止调用筛选器。 因此,当 Filter Graph 管理器停止下一个上游筛选器时,该筛选器不会在 GetBufferReceive 中被阻止,并且可以响应 stop 命令。 上游筛选器可能会在获取停止命令之前提供一些额外的样本,但下游筛选器只是拒绝它们,因为它已经停止。

筛选器图中的数据流