3

我有一个图形端点,它是一个SampleGrabber,我使用回调函数获取所有帧的未压缩数据。

在我的顶级接口代码中,我想要一个函数ReadNextFrame()来获取图中下一帧的数据(直到它到达文件末尾)。

一个性能方面的糟糕实现是将 nextFrameIndex 传递给grabberCB类,指定此时我想要哪个帧。所以我的回调函数会跳过所有其他帧,只选择我想要的帧。这是昂贵的,因为图形必须遍历整个文件才能选择单个帧数据。

我注意到有一个IVideoFrameStep接口,这正是我想要的。但似乎这个接口与 Sample Grabber 不兼容,它的文档说:

在 Microsoft DirectShow 下实现帧精确搜索的解码器必须实现 AM_KSPROPSETID_FrameStep 属性集,该属性集与 IVideoFrameStep 接口一起使用。

我试图将它连接到我的图表,但IVideoFrameStep::CanStep()函数对我返回 false,这意味着我不能将它与 Sample Grabber 一起使用。

所以我的问题是:是否有一个简单且性能方面的好解决方案,这样我就可以让我的图表保持当前状态,然后向前推进一个帧并使用 Sample Grabber 获取数据?

4

1 回答 1

2

您发现它IVideoFrameStep有一定的工作要求,其背后的想法是整个过滤器图进行状态转换,运行和暂停播放一帧。

要使用 Sample Grabber 一次获取所有帧,您可以实现一种更简单的方法,该方法没有任何特殊要求。

  1. 运行您的过滤器图;从图中删除时钟是有意义的 - 见IMediaFilter::SetSyncSource(NULL)
  2. SampleCB通过回调在感兴趣的位置有一个样品采集器
  3. 执行完毕SampleCB后,对数据进行处理,并向运行图表的更高级别代码指示帧可用性
  4. 在里面SampleCB和上面的#3完成后,不要从方法返回,而是陷入等待事件,这表明你已经准备好继续
  5. 高级应用程序代码将处理一个框架并设置上面 #4 中的事件,以允许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
}
于 2017-08-30T17:18:37.727 回答