停止IMFSourceReader时,如何确保不会再次调用OnReadSample?

时间:2019-01-16 21:00:46

标签: thread-safety ms-media-foundation

我正在使用Media Framework SDK从摄像机捕获视频。 我的代码基于MFCaptureD3D示例。 我的代码和本示例使用IMFSourceReader异步读取相机中的帧。为此,该应用程序提供了IMFSourceReaderCallback的实现,该实现的MFSDK线程在每个可用帧时调用OnReadSample。

该示例有效,除了找不到停止摄像头捕获的可靠方法。特别是,即使在源阅读器上调用了Stop和Shutdown之后,偶尔也会调用OnReadSample回调。如果在调用“停止并关闭”后应用程序处置了OnReadSample中使用的资源,则OnReadSample将崩溃。

我正在寻找一个调用,该调用将加入可能仍在调用OnReadSample的所有挂起线程,以便确保该函数返回OnReadSample时不再被调用。

2 个答案:

答案 0 :(得分:0)

后期OnReadSample回调是可能的,这是由于应用程序具有多线程特性,并且此类调用是从辅助线程启动的。与其他为使代码简洁起见而在回调对象实现中降低效率的示例不同,MFCaptureD3D在具有常规引用计数的类CPreview上实现回调。可能有一个较晚的CPreview::OnReadSample调用,然后是IMFSourceReaderCallback::Release调用,该调用预期会删除CPreview实例(除非您出于其他需要引用它)。

话虽如此

  • 确保您的引用计数和界面管理正常
  • 像以前一样停止捕获
  • 准备好进行罕见的后期回调
  • 在接受回调的类中,您可以添加一个标志来指示终止状态,并检查它是否立即返回并且什么也不做,例如here in line 189;当您停止捕获时,还可以在回调类中将此标志设置为忽略延迟调用
  • 在延迟回调的情况下,您的回调类仍然具有来自API的COM接口引用;辅助标志可以保护您免受有害伤害
  • 如果您想确保不再有进一步的回调,可以检查COM接口的释放和回调对象的删除,但是我想说,使用建议的标志,您不必将其用作资源即使可能由于多线程而稍有延迟,也会准确地释放出来

答案 1 :(得分:0)

尽管此处发布的答案和评论很有用,但它们并不是我的问题所在。

实际的问题是在销毁了回调对象之后有一个样本到达。我以为我已经使用我的注释中所述的“标志,互斥体和条件变量”解决了这个问题,但是这种实现是不正确的。

解决该问题的解决方案如下:

  1. 定义两个64位计数器receiveSamples和requestSamples。此外,还有一个“已停止”标志,一个互斥锁和一个条件变量。
  2. 启动后,锁定互斥锁并将计数器设置为0,将停止标志设置为false。然后调用sourceReader-> ReadSample以开始接收第一个样本。
  3. 在“停止”中,锁定互斥锁,将已停止的flog设置为true,然后使用条件变量等待,直到receiveSamples == requestedSamples。
  4. 在OnReadSample中,锁定互斥锁,增加ReceivedSamples计数器,解锁互斥锁并通知条件变量。
  5. 在调用sourceReader-> ReadSample之前,锁定互斥锁(如果尚未拥有)将增加requestSamples计数器。

我将添加一个简短的代码来演示这一点

相关问题