原作者:http://blog.csdn.net/yili_xie/article/details/4803193点击打开链接
在这里讲的是Opencore和OMX的调用sequence,基本来说是根据OMX的API过程来实现的,属于将OMX集成到Opencore的原理部分
对于omx IL的API,大家可以参考http://omxil.sourceforge.net/docs/modules.html
1、将一个CODEC集成到PV Opencore multimedia framewok下的方式主要有三种:作为一个compressed MIO(media I/O) component,或者作为个node,或者作为一个Openmax component集成到Opencore framework下的Openmax codecs nodes。对于各种codec尤其是那些包含了HW acceleratin的codec来说,Openmax IL interface是最直接的和有效的集成方式,为上层提供统一的接口。
2、具体omx component和omxcore的实现在developer文档在讨论,在这里只讨论Opencore和omx core/component的交互作用过程,即call sequence。PVMF对omx的调用大概可以用下面的图来描述:
所有这些过程都是通过PVMF来控制的,由PVMF发出command来控制Opencore component的状态转换。
3、Opencore和OMX core/component的interaction过程分为下面几个过程,所有这些过程都是根据API的典型sequence来实现的。
3.1、PVMF对OMX的调用首先是从对OMXcore的初始化开始的:
@PVMF首先调用OMX_Init来初始化omx core
@ 然后PVMF会向omx core请求所有他所拥有的component,并根据获得的component name,来请求有效component的role,然后对有效的组件及其role建立一个registry。
OMX_Init()用来对omx core进行初始化,它必须是进入omx前调用的第一个函数,而且在调用deinit之前只能被调用一次。
OMX_ComponentNameEnum()实质上就是检测出system run-time时所有的有效component。
OMX_GetRolesOfComponent()实际上根据component name来取得component所支持的role的number。
具体流程如下:
3.2、完成对omx core的初始化之后就要根据开始获得的comonent name,对omx component进行初始化,并且列举出相应component的capabilities以及获得port目录。PVMF的工作流程如下:
@根据component name和role使用OMX_GetHandle来初始化指定的omx component。
@使用所有权index“PV_OMX_CAPABILITY_TYPE_INDEX”根据OMX_GetParameter()取得component的capabilities,根据capabilities就可以知道component是否支持部分祯,是否支持UseBuffer或者AllocateBuffer等等内容。如果OMX componentd对所有权index返回“OMX_ErrorUnsupportedIndex”或者其他错误信息,PVMF必须为component capabilities指定一组默认的数据。
@使用OMX_GetParameter来获得Audio/Video component的有效port数[input/output port],然后遍历所有的输入输出端口,来获得输入输出端口的索引。
PVMF对“PV_OMX_COMPONENT_CAPABILITY_TYPE_INDEX” index的定义如下:
#define PV_OMX_COMPONENT_CAPABILITY_TYPE_INDEX 0xFF7A347
实际上所谓的index包括后面获取Audio/Video component port数使用的“OMX_IndexAudioInit”和“OMX_IndexAudioInit” index都是传到OMX_GetParameter()函数的第一个参数。
PVMF需要从component取得的capabilities被包裹在下面的structure中,需要component对这个structure进行赋值:
typedef struct PV_OMXComponentCapabilityFlagsType
{
OMX_BOOL ilsOMXComponentMultiThreaded;
OMX_BOOL iOMXComponentSupportsExternalOutputBufferAlloc;
OMX_BOOL iOMXComponentSupportsExtrenalInputBufferAlloc;
OMX_BOOL iOMXComponentSupportsMovableInputBuffers;
OMX_BOOL iOMXComponentSupportsPartialFrames;
OMX_BOOL iOMXComponentUsesNALStartCode;
OMX_BOOL iOMXComponentCanHandleIncompleteFrames;
OMX_BOOL iOMXComponentUsesFullAVCFrames;
}
iIsOMXComponentMultiThread默认值为OMX_TRUE,虽然OMX component一般运行在一个独立的线程,但是通过同步调用等方式也可以使其和PVMF运行在一个线程。
iOMXComponentSupportExternalOutput/inputBufferAlloc的默认值为OMX_TRUE,OMX spec要求OMX component必须支持在外部分配的额外buffer(比如OMX_UseBuffer调用外部的buffer),如果Component不支持这个,它必须将其值设为OMX_FALSE,并且和PVMF进行协商,从而使PVMF使用OMX_AllocateBuffer。
IOMXComponentSupportsMovableInputBuffers这个值默认也是OMX_TRUE,他类似于一种动态存储的概念,就是对于external allocated input buffer,可以将其的omx头部和实际数据进行分离,由omx头部的指针来指定实际数据的位置,如果这个指针可变,则component的可以访问不同的数据区域。如果omx component要求其起header总是指向同一个数据区域,则这个值必须设置成false。
iOMXComponentSupportsPartialFrames这个值的默认值为OMX_TRUE,根其字面意义一样,就是component是否支持部分桢,当桢/NAL的大小大于buffer的大小的时候,必须把桢/NAL分割成几块,PVMF会在每个桢的结束位添加“OMX_BUFFERFLAG_ENDOFFRAME”,从而使桢的组装变得很简单,如果component需要由PVMF完成对祯/NAL的组装并提供给component完整的桢/NAL,则必须设置这个值为false,不支持部分桢会对性能造成很大的影响。
iOMXComponentUsesNALStartCode这个值默认是OMX_false,这个标志位主要影响到H264的解码,主要是设计到H264 NAL格式的问题,就是说PVMF能够重构H264的NAL,不需要再让omx component来解些比特流,如果OMX H264 component要求解些比特流,需要提供0x0001 NAL start codes,则这个值必须设置为true。
iOMXComponentCanHandleIncompleteFrames这个值默认为OMX_TRUE,与对partial的支持不同,不完整的桢的是指由于丢包或其他原因导致的桢/NAL不完整,即已经被破坏的桢,comopnent是否能提供恰当的处理,如果component不能相应的处理则必须设置这个值为false。
iOMXComponentUsesFullAVCFrames的值默认为OMX_FALSE,这个值定义了PVMF在使用AVC的情况下,以何种模式为Component提供数据。在OMX_FALSE情况下是采用NAL mode,即PCMF提供给comonent的数据是NAL单元,相反的在OMX_TRUE情况下采用的是Frame. mode,在Frame. mode情况下PVMF必须将NAL单元累在一起,然后为component提供完整的一桢数据。
OMX_GetHandle()根据component name载入指定的component到内存,并根据component的方法来为其创建一个component的instance。
OMX_GetParameter()这实际是一个宏,用来获得component的参数,根据第一个参数handle pointer的不同,可能返回值也是不同的。
具体过程如下:
3.3完成对omx core和omx component的初始化之后,第三个过程就是对omx component input/output buffer的协商。
@首先使用OMX_GetParameter()获得input/output port buffer parameters,然后对获得的parameters进行一个verify,最后调用OMX_SetParameter()对input/output port设置一些buffer parameters。
Component input/output port Buffer size在很大程度上影响着component的性能,如果一个buffer能载入多个桢/NAL就不存在分割的问题,PVMF在每个full桢/NAL后面添加一个“OMX_BUFFERFLAG_ENDOFFRAME”标记。如果一个buffer不够容纳一个桢/NAL,则不管是在输入还是输出都要把桢/NAL分割成多个buffer,并在最后一部分上打上一个end flag的标记。
看OMX API对OMX_AllocateBuffer和OMX_UseBuffer的定义后觉得,所谓分配buffer就是,component每次都要自己分配一个新的buffer和buffer header,而使用buffer,是指可以使用其他component或者IL client分配好的buffer,但必须自己分配一个相应的buffer header,两种方式
具体过程如下:
3.4完成初始化以及对交换区buffer的协商之后,OMX component就被loaded了,载入后的component首先要进入Idle状态。
@首先PVMF会通过OMX_SendCommand函数向OMX component发送状态改变命令,将其状态从OMX_StateLoaded变为OMX_StateIdle。
@然后使用两种分配buffer方式(use or allocate)的任一种来为所有的input/output port分配buffer,分配buffer的函数会根据NumInputBuffer和NumOutputBuffer的值被调用多次[这里有点小疑问,这个Num是不是就是port的数目?]
@当component完成state transition以后,会通过envenhandle callback来通知PVMF(OMX_EventCmdComplete)。
根据OMX spec,所有的标准OMX component必须支持OMX_UseBuffer/Allocate两种分配buffer的方式,如果由于内部限制等原因不支持的话,component必须与PVMF进行协商。
一般来说INPUT bufferes一般分配在component外部,这样输入数据就可以省去不必要的copy操作。
具体过程如下:
![](https://p-blog.csdn.net/images/p_blog_csdn_net/yili_xie/EntryImages/20091112/load.jpg)