传送示例

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

本文介绍筛选器如何提供示例。 它描述了使用 IMemInputPin 方法的推送模型和使用 IAsyncReader 的拉取模型。

推送模型:提供示例

输出引脚通过调用 IMemInputPin::Receive 方法或 IMemInputPin::ReceiveMultiple 方法(等效但提供样本数组)来提供示例。 输入引脚可以阻止 接收 (或 ReceiveMultiple) 。 如果引脚可能会阻止,则其 IMemInputPin::ReceiveCanBlock 方法应返回S_OK。 如果引脚保证永远不会阻止, ReceiveCanBlock 应返回S_FALSE。 S_OK返回值并不意味着 Receive 始终阻止,只是它可能会阻止。

虽然 Receive 可以阻止等待资源可用,但不应阻止它等待上游筛选器中的更多数据。 这样做可能会导致死锁,其中上游筛选器等待下游筛选器释放示例,这永远不会发生,因为下游筛选器正在等待上游筛选器。 但是,如果筛选器有多个输入引脚,则一个引脚可以等待另一个引脚接收数据。 例如, AVI 复用器 筛选器执行此操作,以便它可以交错音频和视频数据。

引脚可能会出于多种原因拒绝示例:

  • 引脚正在刷新 (请参阅 刷新) 。
  • 引脚未连接。
  • 筛选器已停止。
  • 发生了其他一些错误。

在第一种情况下 ,Receive 方法应返回S_FALSE,在其他情况下应返回失败代码。 当返回代码不是S_OK时,上游筛选器应停止发送示例。

可以将前三种情况视为“预期”故障,即筛选器处于接收样本的错误状态。 意外故障将导致引脚拒绝示例,即使引脚处于接收状态。 如果发生此类型的错误,引脚应向下游发送流结束通知,并将 EC_ERRORABORT 事件发送到 Filter Graph 管理器。

在 DirectShow 基类中, CBaseInputPin::CheckStreaming 方法会检查常规故障案例-刷新、停止等。 派生类需要检查特定于筛选器的故障。 如果出现错误, CBaseInputPin::Receive 方法会发送流结束通知和EC_ERRORABORT事件。

拉取模型:请求示例

IAsyncReader 接口中,输入引脚通过调用以下方法之一从输出引脚请求样本:

Request 方法是异步的;输入引脚调用 IAsyncReader::WaitForNext 以等待请求完成。 其他两种方法是同步的。

何时传递数据

筛选器始终在处于运行状态时提供示例。 在大多数情况下,筛选器还会在暂停时提供示例。 这使图形能够提示数据,以便在调用 “运行” 时立即开始播放 (请参阅 筛选状态) 。 如果筛选器在暂停时未传递数据,则筛选器的 IMediaFilter::GetState 方法应返回处于暂停状态的VFW_S_CANT_CUE。 此返回代码指示筛选器图在完成暂停转换之前不会等待筛选器中的数据。 否则, Pause 方法将无限期阻止。 有关示例代码,请参阅 CBaseFilter::GetState

下面是筛选器何时可能需要返回VFW_S_CANT_CUE的一些示例:

  • 实时源(如捕获筛选器)在暂停时不应发送数据。 请参阅 在捕获筛选器中生成数据
  • 拆分器筛选器在暂停时可能会发送数据,也可能不发送数据,具体取决于实现。 如果筛选器使用单独的线程在每个输出引脚上对数据进行排队,则它可以在暂停时发送数据。 但是,如果筛选器为每个输出引脚使用单个线程,则第一个引脚可能会在调用 Receive 时阻止该线程,这将阻止其他引脚发送数据。 在这种情况下,应返回VFW_S_CANT_CUE。
  • 筛选器可能会偶尔传递数据。 例如,它可能会分析自定义数据流,并在传递其他数据包时筛选掉某些数据包。 在这种情况下,可能无法保证筛选器在暂停时提供数据。

源筛选器 (使用推送模型) 或分析器筛选器 (使用推送/拉取模型) 创建一个或多个流式处理线程,从而尽快提供示例。 下游筛选器(如解码器和转换)通常仅在其输入引脚上调用 Receive 时才发送数据。

接收和传送示例