环境
用例
问题描述
第一个启用了“摄像机输入”端口(端口#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说此成员是同步设置的:当事情“起作用”时,我认为这是正在发生的事情:
bEnabled
为OMX_TRUE
(立即发生)。 OMX_CommandPortEnable
事件回调。 您可能会错误地认为它按此顺序发生:
bEnabled
为OMX_TRUE
(立即发生)。 OMX_CommandPortEnable
事件回调。 这使得使用条件变量似乎可以某种方式改变OpenMAX的行为。实际上,
bEnabled
和OMX_CommandPortEnable
回调并没有真正报告相同的内容。我认为在启用端口和分配其缓冲区之间不需要任何同步(或期望)。关于c++ - RPi2,OpenMAX,死锁,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34545625/