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

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

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

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



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

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

最佳答案

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

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

  • 运行您的过滤器图;从图中删除时钟是有意义的 - 请参阅 IMediaFilter::SetSyncSource(NULL)
  • 使用 SampleCB 回调
  • 在感兴趣的位置有一个 Sample Grabber
  • 一旦你的 SampleCB 被执行,就用数据做你的事情并向运行图的更高级别的代码指示帧的可用性
  • 在完成 SampleCB 和上面的#3 之后,不要从方法中返回而是进入等待事件,这表明您已准备好继续
  • 高级应用程序代码将处理一个帧并设置上面#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
    }
    

    关于c++ - ISampleGrabberFilter 一次一帧步,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45962088/

    10-11 19:38