解析以OpenMAX非Tunneled为例,从应用线程开始。
一、应用线程基本流程
1. OMX_Init()
2. 获取句柄,组件转到Loaded状态
OMX_GetHandle(out handle, in componentName, in appData, in callbacks);
其中callbacks结构包括三个回调函数指针(作用后文介绍):
1) EventHandler
2) EmptyBufferDone
3) FillBufferDone
3. 参数交互
如:
OMX_GetParameter(in handle, in type, out param);
OMX_SetParameter(in handle, in type, in param);
其中关键需要设置每个端口上的Buffer数量,一般采用2个Buffer,如下对端口参数进行设置:
paramPort.nBufferCountActual = 2;
具体参数详见后文介绍
4. 命令组件转到Idle状态
OMX_SendCommand(in handle, in cmd = OMX_CommandStateSet, in nParam = OMX_StateIdle, in pCmdData = 0);
5. Idle期准备
包括:
1) Buffer分配
2) 等待组件正式转到Idle状态,这个由信号量控制。这个信号量在上述EventHandler回调函数中put,而这个回调函数在状态转换完毕以后作为OMX_EventCmdComplete事件的响应被调用。
6. 组件转到Executing状态
OMX_SendCommand(in handle, in cmd = OMX_CommandStateSet, in nParam = OMX_StateExecuting, in pCmdData = 0);
命令组件转到Executing状态
等待转换完成,同样用信号量控制。
7. 初始化端口Buffer并绑定
通过调用OMX_FillThisBuffer设置组件的输出Buffer
通过调用OMX_EmptyThisBuffer设置组件的输入Buffer,此处可为输入Buffer加载初始数据流。
8. 主线程消息循环
在这里等待应用信号量,其中包括组件完毕的消息,用以退出循环。
9. 收尾工作1:命令并等待组件进入Idle状态
10. 收尾工作2:命令并等待组件进入Loaded状态,并销毁Buffer
11. 释放组件句柄
二、组件缓冲处理
当组件完成数据输出(Fill Buffer)后会调用FillBufferDone回调函数以通知应用层准备数据(仅非Tunneled模式)
函数C代码原型:
FillBufferDone(OMX_OUT OMX_HANDLETYPE hComponent, OMX_OUT OMX_PTR pAppData, OMX_OUT OMX_BUFFERHEADERTYPE *pBuffer)
其中hComponent是组件句柄;pAppData为GetHandle时赋入的应用数据;pBuffer为缓冲地址。由于该缓冲已经填写完毕(通常是一帧完成),回调函数将改数据输出到适当位置,完后再次调用OMX_FillThisBuffer,链入下一轮工作。
当组件完成数据消耗(Empty Buffer)后会调用EmptyBufferDone回调函数以通知应用层准备数据(仅非Tunneled模式)
函数C代码原型:
EmptyBufferDone(OMX_OUT OMX_HANDLETYPE hComponent, OMX_OUT OMX_PTR pAppData, OMX_OUT OMX_BUFFERHEADERTYPE *pBuffer)
三个参数含义同上。由于改缓冲已经消耗殆尽,回调函数将读入数据载入缓冲,完后再次调用OMX_EmptyThisBuffer,链入下一轮工作。
上述缓冲操作是组件运行的一个环节,OpenMAX组件运行于一个独立线程。
三、组件事件处理
当组件接收到一个OpenMAX事件时会调用EventHandler
EventHandler(OMX_OUT OMX_HANDLETYPE hComponent, OMX_OUT OMX_PTR pAppData, OMX_OUT OMX_EVENTTYPE eEvent, OMX_OUT OMX_U32 nData1, OMX_OUT OMX_U32 nData2, OMX_IN OMX_PTR pEventData);
其中前两个参数已在第二章介绍。eEvent为事件代号,例如第一章提到的OMX_SendCommand,对命令完成的所引发的事件即OMX_EventCmdComplete。
nData1和nData2是该事件的两个关联数据。例如,对于命令完成事件,如果命令为状态切换,其中nData1即OMX_CommandStateSet;nData2即对应的目标状态,如OMX_StateIdle等。又如对于缓冲事件,其eEvent为OMX_EventBufferFlag,当nData2为OMX_BUFFERFLAG_EOS时往往说明输入码流结束,从而对该事件的响应通常是设置EOF标记并put信号量通知处于循环中的应用线程。
一、应用线程基本流程
1. OMX_Init()
2. 获取句柄,组件转到Loaded状态
OMX_GetHandle(out handle, in componentName, in appData, in callbacks);
其中callbacks结构包括三个回调函数指针(作用后文介绍):
1) EventHandler
2) EmptyBufferDone
3) FillBufferDone
3. 参数交互
如:
OMX_GetParameter(in handle, in type, out param);
OMX_SetParameter(in handle, in type, in param);
其中关键需要设置每个端口上的Buffer数量,一般采用2个Buffer,如下对端口参数进行设置:
paramPort.nBufferCountActual = 2;
具体参数详见后文介绍
4. 命令组件转到Idle状态
OMX_SendCommand(in handle, in cmd = OMX_CommandStateSet, in nParam = OMX_StateIdle, in pCmdData = 0);
5. Idle期准备
包括:
1) Buffer分配
2) 等待组件正式转到Idle状态,这个由信号量控制。这个信号量在上述EventHandler回调函数中put,而这个回调函数在状态转换完毕以后作为OMX_EventCmdComplete事件的响应被调用。
6. 组件转到Executing状态
OMX_SendCommand(in handle, in cmd = OMX_CommandStateSet, in nParam = OMX_StateExecuting, in pCmdData = 0);
命令组件转到Executing状态
等待转换完成,同样用信号量控制。
7. 初始化端口Buffer并绑定
通过调用OMX_FillThisBuffer设置组件的输出Buffer
通过调用OMX_EmptyThisBuffer设置组件的输入Buffer,此处可为输入Buffer加载初始数据流。
8. 主线程消息循环
在这里等待应用信号量,其中包括组件完毕的消息,用以退出循环。
9. 收尾工作1:命令并等待组件进入Idle状态
10. 收尾工作2:命令并等待组件进入Loaded状态,并销毁Buffer
11. 释放组件句柄
二、组件缓冲处理
当组件完成数据输出(Fill Buffer)后会调用FillBufferDone回调函数以通知应用层准备数据(仅非Tunneled模式)
函数C代码原型:
FillBufferDone(OMX_OUT OMX_HANDLETYPE hComponent, OMX_OUT OMX_PTR pAppData, OMX_OUT OMX_BUFFERHEADERTYPE *pBuffer)
其中hComponent是组件句柄;pAppData为GetHandle时赋入的应用数据;pBuffer为缓冲地址。由于该缓冲已经填写完毕(通常是一帧完成),回调函数将改数据输出到适当位置,完后再次调用OMX_FillThisBuffer,链入下一轮工作。
当组件完成数据消耗(Empty Buffer)后会调用EmptyBufferDone回调函数以通知应用层准备数据(仅非Tunneled模式)
函数C代码原型:
EmptyBufferDone(OMX_OUT OMX_HANDLETYPE hComponent, OMX_OUT OMX_PTR pAppData, OMX_OUT OMX_BUFFERHEADERTYPE *pBuffer)
三个参数含义同上。由于改缓冲已经消耗殆尽,回调函数将读入数据载入缓冲,完后再次调用OMX_EmptyThisBuffer,链入下一轮工作。
上述缓冲操作是组件运行的一个环节,OpenMAX组件运行于一个独立线程。
三、组件事件处理
当组件接收到一个OpenMAX事件时会调用EventHandler
EventHandler(OMX_OUT OMX_HANDLETYPE hComponent, OMX_OUT OMX_PTR pAppData, OMX_OUT OMX_EVENTTYPE eEvent, OMX_OUT OMX_U32 nData1, OMX_OUT OMX_U32 nData2, OMX_IN OMX_PTR pEventData);
其中前两个参数已在第二章介绍。eEvent为事件代号,例如第一章提到的OMX_SendCommand,对命令完成的所引发的事件即OMX_EventCmdComplete。
nData1和nData2是该事件的两个关联数据。例如,对于命令完成事件,如果命令为状态切换,其中nData1即OMX_CommandStateSet;nData2即对应的目标状态,如OMX_StateIdle等。又如对于缓冲事件,其eEvent为OMX_EventBufferFlag,当nData2为OMX_BUFFERFLAG_EOS时往往说明输入码流结束,从而对该事件的响应通常是设置EOF标记并put信号量通知处于循环中的应用线程。