筛选状态

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

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

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

源 > 转换 > 呈现器

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

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

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

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

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

状态转换

Filter Graph 管理器按上游顺序执行所有状态转换,从呈现器开始,向后工作到源筛选器。 这种排序是必要的,以防止样本被丢弃,并防止图形死锁。 最重要的状态转换是在暂停和停止之间:

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

筛选器图 中的 数据流