Environment
- Raspberry Pi 2 B+
- Debian Linux
- OpenMAX IL
Use-case
- OpenMAX Camera Video capture
- Camera ports are disabled
- Renderer / Camera Tunnel is set
- All components state is set to Idle
- Ports are enabled
Problem description
The first port being enabled to the Camera Input port ( Port #73 ), the port is being enabled using the “OMX_CommandPortEnable” command, as with the “OMX_CommandPortDisable” command, it is expected for the camera component to fire it’s “OMX_CALLBACKTYPE::EventHandler” event handler having “eEvent == OMX_EventCmdComplete” and “nData1 == OMX_CommandPortEnable”, however, this never happen and the application infinitely wait for the port to become enabled.
Problem Analysis
I am using std::condition_variable in conjunction with std::mutex to wait for the state change to complete, hence, OMX_CALLBACKTYPE::EventHandler updates the condition variable and calls “notify_one()” while the caller thread locks std::mutex and wait for the condition variable to be set, using this approach “OMX_CALLBACKTYPE::EventHandler” is never called ( with any argument ), and the program locks forever.
NOTE: When waiting for the condition variable the mutex is verified not to be owned, this is done by verifying (0 == std::mutex::__owner).
HOWEVER, All works fine when polling the status of the port by calling usleep and OMX_GetParameter(OMX_IndexParamPortDefinition) iteratively.
Question at hand
Why is “OMX_CALLBACKTYPE::EventHandler” triggered when polling it’s value and NOT triggered when using a conditional_variable? With windows there is the notion of APC & Alertable threads, is there any equivalent in linux? One that can explain the above mentioned?
Advertisement
Answer
My experience is that enabling a port does not issue the event callback until the port is populated with buffers. That is, the sequence is:
- Set port to enabled (
OMX_SendCommand()
withOMX_CommandPortEnable
). - Populate port buffers (
OMX_AllocateBuffer()
orOMX_UseBuffer()
). - Receive
OMX_CommandPortEnable
event callback.
If you wait for the event callback before you allocate the buffers then you will have deadlock.
When you poll by testing OMX_PARAM_PORTDEFINITIONTYPE.bEnabled
, that is going to return OMX_TRUE
immediately because the spec says this member is set synchronously:
The port shall immediately set
bEnabled
in its port definition structure when the port receivesOMX_CommandPortEnable
.
Here’s what I think is happening for you when things “work”:
- Set port to enabled.
- Poll until
bEnabled
isOMX_TRUE
(which happens immediately). - Populate port buffers.
- Receive
OMX_CommandPortEnable
event callback.
You may be mistakenly thinking that it happens in this order instead:
- Set port to enabled.
- Poll until
bEnabled
isOMX_TRUE
(which happens immediately). - Receive
OMX_CommandPortEnable
event callback. - Populate port buffers.
This makes it seem that using a condition variable somehow changes OpenMAX behavior. In actuality bEnabled
and the OMX_CommandPortEnable
callback aren’t really reporting the same thing. I don’t believe that any synchronization is necessary (or desirable) between enabling the port and allocating its buffers.