在捕获筛选器中生成数据
[与此页面关联的功能 DirectShow 是旧版功能。 它已被 MediaPlayer、 IMFMediaEngine 和 Media Foundation 中的音频/视频捕获所取代。 这些功能已针对Windows 10和Windows 11进行了优化。 Microsoft 强烈建议新代码尽可能在 Media Foundation 中使用 MediaPlayer、 IMFMediaEngine 和 音频/视频捕获 ,而不是 DirectShow。 如果可能,Microsoft 建议重写使用旧 API 的现有代码以使用新 API。]
本主题介绍自定义 DirectShow 捕获筛选器应如何生成输出数据。
筛选器状态更改
仅当筛选器正在运行时,捕获筛选器才应生成数据。 当筛选器暂停时,不要从固定发送数据。 此外,在筛选器暂停时,从 CBaseFilter::GetState 方法返回VFW_S_CANT_CUE。 此返回值通知 Filter Graph 管理器,在筛选器暂停时不应等待筛选器中的任何数据。 有关详细信息,请参阅 筛选状态。
以下代码演示如何实现 IMediaFilter::GetState 方法:
CMyVidcapFilter::GetState(DWORD dw, FILTER_STATE *pState)
{
CheckPointer(pState, E_POINTER);
*pState = m_State;
if (m_State == State_Paused)
{
return VFW_S_CANT_CUE;
}
else
{
return S_OK;
}
}
控制单个流
捕获筛选器的输出引脚应支持 IAMStreamControl 接口,以便应用程序可以单独打开或关闭每个引脚。 例如,应用程序可以在不捕获的情况下预览,然后在不重新生成筛选器图的情况下切换到捕获模式。 可以使用 CBaseStreamControl 类来实现此接口。
时间戳
当筛选器捕获样本时,使用当前流时间标记该示例。 结束时间是开始时间加上持续时间。 例如,如果筛选器每秒捕获 10 个样本,当筛选器捕获样本时流时间为 200,000,000 单位,则时间戳应为 200000000 和 201000000。 (每秒有 10,000,000 个单位。)
若要计算流时间,请调用 IReferenceClock::GetTime 方法来获取当前引用时间,然后子化原始开始时间。 或者,调用 CBaseFilter::StreamTime 方法,该方法执行相同的计算。 若要在示例上设置时间戳,请调用 IMediaSample::SetTime 方法。
但是,如果筛选器具有预览固定,则预览引脚中的示例不应具有时间戳。 原因是样本始终在捕获后稍稍到达呈现器。 如果样本带有时间戳,呈现器会将它们视为延迟,并且可能会尝试通过删除样本来追赶。 (有关详细信息,请参阅 DirectShow 视频捕获筛选器。) 请注意 ,IAMStreamControl 接口需要引脚来跟踪采样时间。 对于预览固定,可能需要修改实现,使其不依赖于时间戳。
时间戳必须始终从一个样本增加到下一个样本。 即使筛选器暂停,也是如此。 如果筛选器运行、暂停,然后再次运行,则暂停后的第一个示例必须具有比暂停前的最后一个样本更大的时间戳。
根据要捕获的数据,可能适合在样本上设置媒体时间。
有关详细信息,请参阅 DirectShow 中的时间和时钟。
相关主题