ISampleGrabberFilter 一次一帧
ISampleGrabberFilter one frame step at a time
我有一个图表终点是 SampleGrabber,我在其中使用回调函数获取所有帧的未压缩数据。
在我的顶级接口代码中,我想要一个函数 ReadNextFrame() 来获取图中下一帧的数据(直到它到达文件末尾) .
一个性能方面的错误实现是将 nextFrameIndex 传递给 grabberCB class 指定此时我想要的帧。所以我的回调函数会跳过所有其他帧,只选择我想要的帧。这是昂贵的,因为图表必须遍历整个文件以选择单个帧数据。
我注意到有一个 IVideoFrameStep 界面,这正是我想要的。但是这个接口似乎与 Sample Grabber 不兼容,它的文档说:
Decoders that implement frame-accurate seeking under Microsoft
DirectShow must implement the AM_KSPROPSETID_FrameStep property set,
which is used in conjunction with the IVideoFrameStep interface.
我试图将它连接到我的图形,但是 IVideoFrameStep::CanStep() 函数为我返回了 false,这意味着我不能将它与 Sample Grabber 一起使用。
所以我的问题是:是否有一个简单且性能好的解决方案,这样我可以让我的图表保持当前状态,然后向前制作一个帧并使用 Sample Grabber 获取数据?
您发现 IVideoFrameStep
有特定的工作要求,其背后的想法是整个过滤器图进行状态转换、运行和暂停,正好播放一帧。
要使用 Sample Grabber 一次获取所有帧,您可以实施一种更简单的方法,该方法没有任何特殊要求。
- 有你的过滤图运行;从图表中删除时钟是有意义的 - 请参阅
IMediaFilter::SetSyncSource(NULL)
- 在感兴趣的位置有一个样本采集器,带有
SampleCB
回调
- 执行
SampleCB
后,对数据进行操作并向运行图形的更高级别代码指示帧可用性
- 虽然在
SampleCB
和上面的 #3 已经完成,但不要从方法中 return 而是陷入等待事件,这表明您已准备好继续
- 高级应用程序代码将处理帧并设置上面#4 中的事件,允许
SampleCB
退出并进一步获取新帧;使用您从上面的#3 重复的新框架。
也就是说,您的 SampleCB
等待会锁定整个管道,在所需的时间内保持其状态,让您以方便的速度逐帧处理。
SampleCB
的伪代码是(手动 set/reset 事件):
data m_Data;
event m_DataAvailability;
event m_NextFrameRequest;
void SampleCB(Frame)
{
m_Data = Frame.GetData();
m_DataAvailability.Set();
m_NextFrameRequest.WaitFor(); // Sleeping here until signaled to continue
m_NextFrameRequest.Reset();
}
data ReadNextFrame()
{
m_DataAvailability.WaitFor();
data Data = m_Data;
m_DataAvailability.Reset(); // Current data processed, we need next portion
m_NextFrameRequest.Set(); // Indicate that we allow next callback call
return Data; // Make captured frame available
}
我有一个图表终点是 SampleGrabber,我在其中使用回调函数获取所有帧的未压缩数据。
在我的顶级接口代码中,我想要一个函数 ReadNextFrame() 来获取图中下一帧的数据(直到它到达文件末尾) .
一个性能方面的错误实现是将 nextFrameIndex 传递给 grabberCB class 指定此时我想要的帧。所以我的回调函数会跳过所有其他帧,只选择我想要的帧。这是昂贵的,因为图表必须遍历整个文件以选择单个帧数据。
我注意到有一个 IVideoFrameStep 界面,这正是我想要的。但是这个接口似乎与 Sample Grabber 不兼容,它的文档说:
Decoders that implement frame-accurate seeking under Microsoft DirectShow must implement the AM_KSPROPSETID_FrameStep property set, which is used in conjunction with the IVideoFrameStep interface.
我试图将它连接到我的图形,但是 IVideoFrameStep::CanStep() 函数为我返回了 false,这意味着我不能将它与 Sample Grabber 一起使用。
所以我的问题是:是否有一个简单且性能好的解决方案,这样我可以让我的图表保持当前状态,然后向前制作一个帧并使用 Sample Grabber 获取数据?
您发现 IVideoFrameStep
有特定的工作要求,其背后的想法是整个过滤器图进行状态转换、运行和暂停,正好播放一帧。
要使用 Sample Grabber 一次获取所有帧,您可以实施一种更简单的方法,该方法没有任何特殊要求。
- 有你的过滤图运行;从图表中删除时钟是有意义的 - 请参阅
IMediaFilter::SetSyncSource(NULL)
- 在感兴趣的位置有一个样本采集器,带有
SampleCB
回调 - 执行
SampleCB
后,对数据进行操作并向运行图形的更高级别代码指示帧可用性 - 虽然在
SampleCB
和上面的 #3 已经完成,但不要从方法中 return 而是陷入等待事件,这表明您已准备好继续 - 高级应用程序代码将处理帧并设置上面#4 中的事件,允许
SampleCB
退出并进一步获取新帧;使用您从上面的#3 重复的新框架。
也就是说,您的 SampleCB
等待会锁定整个管道,在所需的时间内保持其状态,让您以方便的速度逐帧处理。
SampleCB
的伪代码是(手动 set/reset 事件):
data m_Data;
event m_DataAvailability;
event m_NextFrameRequest;
void SampleCB(Frame)
{
m_Data = Frame.GetData();
m_DataAvailability.Set();
m_NextFrameRequest.WaitFor(); // Sleeping here until signaled to continue
m_NextFrameRequest.Reset();
}
data ReadNextFrame()
{
m_DataAvailability.WaitFor();
data Data = m_Data;
m_DataAvailability.Reset(); // Current data processed, we need next portion
m_NextFrameRequest.Set(); // Indicate that we allow next callback call
return Data; // Make captured frame available
}