1

环境

  • 树莓派 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”永远不会被调用(带有任何参数),并且程序永远锁定。
注意:当等待条件变量时,互斥锁被验证为不被拥有,这是通过验证 (0 == std::mutex::__owner) 来完成的。
但是,通过迭代调用 usleep 和 OMX_GetParameter(OMX_IndexParamPortDefinition) 轮询端口状态时,一切正常。

手头的问题

为什么在轮询它的值时会触发“OMX_CALLBACKTYPE::EventHandler”,而在使用 conditional_variable 时不会触发?对于 Windows,有 APC 和 Alertable 线程的概念,在 linux 中是否有任何等价物?一个可以解释上面提到的?

4

1 回答 1

1

我的经验是,在端口填充缓冲区之前,启用端口不会发出事件回调。也就是说,顺序是:

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

如果在分配缓冲区之前等待事件回调,那么您将陷入死锁。

当您通过 testing 进行轮询时OMX_PARAM_PORTDEFINITIONTYPE.bEnabled,它将立即返回OMX_TRUE,因为规范说该成员是同步设置的:

当端口接收到时,端口应立即bEnabled在其端口定义结构中设置OMX_CommandPortEnable

当事情“起作用”时,我认为您会发生以下情况:

  • 将端口设置为启用。
  • 轮询直到bEnabledOMX_TRUE(立即发生)。
  • 填充端口缓冲区。
  • 接收OMX_CommandPortEnable事件回调。

您可能错误地认为它是按以下顺序发生的:

  • 将端口设置为启用。
  • 轮询直到bEnabledOMX_TRUE(立即发生)。
  • 接收OMX_CommandPortEnable事件回调。
  • 填充端口缓冲区。

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

于 2016-01-28T22:09:53.257 回答