环境

  • 树莓派2 B +
  • Debian Linux的
  • OpenMAX IL

  • 用例
  • OpenMAX摄像机视频捕获
  • 相机端口已禁用
  • 渲染器/相机隧道设置为
  • 所有组件状态均设置为空闲
  • 已启用端口

  • 问题描述

    第一个启用了“摄像机输入”端口(端口#73)的端口,使用“OMX_CommandPortEnable”命令启用了该端口,与“OMX_CommandPortDisable”命令一样,期望摄像机组件触发它的“OMX_CALLBACKTYPE:”: EventHandler”事件处理程序具有“eEvent == OMX_EventCmdComplete”和“nData1 == OMX_CommandPortEnable”,但是,这永远不会发生,并且应用程序会无限期地等待端口启用。

    问题分析

    我将std::condition_variable与std::mutex结合使用以等待状态更改完成,因此,OMX_CALLBACKTYPE::EventHandler将更新条件变量并调用“notify_one()”,而调用方线程将锁定std::mutex和等待条件变量的设置,使用这种方法“OMX_CALLBACKTYPE::EventHandler”永远不会被调用(带有任何参数),并且程序将永远锁定。
    注意:WAITING条件变量时,互斥量不被确认为拥有,这是通过验证(0 == std::mutex::__ owner)来完成的。
    但是,当通过迭代调用usleep和OMX_GetParameter(OMX_IndexParamPortDefinition)轮询端口状态时,所有方法都可以正常工作。

    手头的问题

    为什么在轮询值时会触发“OMX_CALLBACKTYPE::EventHandler”,而在使用conditional_variable时却不会触发?在Windows中,有APC和Alertable线程的概念,在Linux中是否有等效的概念?可以解释上面提到的一个吗?

    最佳答案

    我的经验是,启用端口并不会发出事件回调,除非该端口装有缓冲区。即,顺序为:

  • 将端口设置为启用(OMX_SendCommand()OMX_CommandPortEnable)。
  • 填充端口缓冲区(OMX_AllocateBuffer()OMX_UseBuffer())。
  • 接收OMX_CommandPortEnable事件回调。

  • 如果在分配缓冲区之前等待事件回调,则将出现死锁。

    当您通过测试OMX_PARAM_PORTDEFINITIONTYPE.bEnabled进行轮询时,这将立即返回OMX_TRUE,因为the spec说此成员是同步设置的:



    当事情“起作用”时,我认为这是正在发生的事情:
  • 将端口设置为启用。
  • 轮询直到bEnabledOMX_TRUE(立即发生)。
  • 填充端口缓冲区。
  • 接收OMX_CommandPortEnable事件回调。

  • 您可能会错误地认为它按此顺序发生:
  • 将端口设置为启用。
  • 轮询直到bEnabledOMX_TRUE(立即发生)。
  • 接收OMX_CommandPortEnable事件回调。
  • 填充端口缓冲区。

  • 这使得使用条件变量似乎可以某种方式改变OpenMAX的行为。实际上,bEnabledOMX_CommandPortEnable回调并没有真正报告相同的内容。我认为在启用端口和分配其缓冲区之间不需要任何同步(或期望)。

    关于c++ - RPi2,OpenMAX,死锁,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34545625/

    10-11 18:49