我的图表结束点是 SampleGrabber ,其中我使用回调函数获取所有帧的未压缩数据。
在我的顶级界面代码中,我希望有一个函数 ReadNextFrame(),它可以获取图中下一帧的数据(直到它到达文件末尾)。
性能差的实现方法是将 nextFrameIndex 传递给grabberCB类,指定此时我想要的帧。所以我的回调函数会跳过所有其他帧,并只选择我想要的那个。这是昂贵的,因为图表必须遍历整个文件以选择单个帧数据。
我注意到有一个 IVideoFrameStep 界面,这是我想要的理想选择。但似乎这个界面与Sample Grabber不兼容,它的文档说:
在Microsoft下实现帧精确搜索的解码器 DirectShow必须实现AM_KSPROPSETID_FrameStep属性集, 它与IVideoFrameStep接口一起使用。
我尝试将其连接到我的图表,但 IVideoFrameStep :: CanStep()函数对我来说返回false,这意味着我无法将其与Sample Grabber一起使用。
所以我的问题是:是否有一个简单且性能良好的解决方案,因此我可以让我的图表保持当前状态,然后使用单帧前进并使用Sample Grabber获取数据?
答案 0 :(得分:2)
您发现IVideoFrameStep
有一定的工作要求,其背后的想法是整个过滤器图形执行状态转换,运行和暂停只播放一帧。
要使用Sample Grabber逐个获取所有帧,您可以实现更简单的方法,没有任何特殊要求。
IMediaFilter::SetSyncSource(NULL)
SampleCB
回调SampleCB
后,对数据执行操作并指示运行图表的更高级代码的框架可用性SampleCB
和#3内部完成时,不要从方法返回而是等待事件,这表示您已准备好继续SampleCB
退出并进一步获取新帧;使用上面#3重复的新框架。也就是说,您的SampleCB
等待锁定整个管道,保持其状态所需的时间,让您以方便的速度逐帧处理。
SampleCB
的伪代码(带手动设置/重置事件):
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
}