因为相关的omx spec还没有仔细阅读过,所以在这里只是对这个文档进行简单的翻译性阅读,很多概念都要在了解玩omx spec后才清楚。理解omx core integration 之前需要理解的文档:
1、 openmax integration layer application programming interface specification
http://www.khronos.org/openmax/
2、opemmax call sequence
要将一个omx core集成到PVMF下,要考虑的是两个问题:一个是omx core必须满足什么条件才能集成进PVMF,另外如果在PVMF内如果包含多个omx core的时候,因为每个omx core都实现了相同的API,因此要考虑如何兼容的问题。
A、 PV omx test harness
在集成omx component之前,首先要验证一下其是否能进行正确的工作。通过一系列一致性测试,在comonent集成进PVMF之前对其功能check。PV提供一套PV omx test harness对component进行性能测试。
Test hardness只允许有一个omx core,但这个omx core可以同时链接多个omx component,因为只有一个omx core,因此在测试过程中就不存在多个omx core共存的冲突问题。
PV omx test harness的source在:
解码: …/codecs_v2/omx/omx_testapp/
编码: …/codecs_v2/omx/omx_testapp_enc/
必 须提供makefile来将omx plugin编译进test harness,当对test harness source进行编译时,必须修改makefile将需要测试的omx plugin library链接进来。这些omx plugin libray必须包含标准omx core的实现,比如OMX_init() OMX_Deinit等等,相关的makefile在以下目录:
解码: …/codecs_v2/omx/omx_testapp/build/makefile_omx_plugin
编码: …/codecs_v2/omx/omx_testapp_enc/build/makefile_omx_plugin
如何在命令 行中运行PV omx test harness的说明在以下目录:
解码:…/codecs_v2/omx/omx_testapp/doc/…
编码:…/codecs_v2/omx/omx_testapp_enc/doc/…
一旦通过测试,就可以进行下一步集成。
【这 个plugin libray是只是omx标准的library么?还是已经加入了对opencore的封装?个人觉得应该是经过封装的,plugin就是一个封装的过 程,不然测试就失去了意义。因为最新的Opencore 2.02版本还没有发现关于这个test harness的相关文档和source,估计要等source出来确认。】
对 于omx core来说,他必须实现所有的spec要求的API,但对于component,如果只是对spec的部分支持,比如说不支持 OMX_UseBuffer,同样可以集成到PVMF,但是它必须与PVMF进行协商,具体协商过程可以参照omx call sequence。
B、 编译OMX core library
1. OMX core methods
PV opencore framework是作为一个Openmax IL client来与omx core以及基础component来进行通信的。Omx core的功能就是为了实现初始化,比如说component的实例 化。 如果要将omx component集成进PVMF必须提供相应的omx core,并且所有的component和相应的omx core都必须在同一个libray。换句话说就是供应商不能集成一个分立的component进入一个已经存在的其他PV omx core,这是因为omx core与component之间通信是采用的特定的API,不能将自己的component集成到一个陌生的PV omx core下。PV omx core和PV omx component之间的API是一个内部实现的spec,不是又omx标准规定的,而且可以随时由PV来改变,因此如果一个供应商要集成一个 component,必须附带与之匹配的omx core。
Omx core spec规定了OMX core的9种方法,所有这些方法都必须在库中存在,不过对某些不需要的方法可以提供不完整的实现,比如说OMX_SetupTunnel有时候是不需要 的,那简单地返回”OMX_ErrorNotImplemented”就可以了。
1) OMX_init
2) OMX_Deinit
3) OMX_GetHandle
4) OMX_FreeHandle
5) OMX_ComponentNameEnum
6) OMX_GetComponentsOfRole
7) OMX_GetRolesOfComponent
8) OMX_SetupTunnel
9) OMX_GetContenPipe
2. Co-existence of multiple OMX cores
对于不同供应商提供的多个omx core共存的主要问题是他们都需要实现同样的OMX core method,PVMF采用动态载入和链接多个OMX core的方法来解决 这 个问题。PVMF通过一个wrapper layer来调用omx core的核心方法,实现这部分操作的source在…/codecs_v2/omx/omx_mastercore/…中,通过这个方法,每个omx core都可以保持其omx core method的名字为spec要求名字,但是PVMF会对要集成的omx core liarary加上一定要求,具体要求参照下面的内容。
【看了下omx_mastercore.cpp这个文件 ,虽然c++写的类和函数看得不是很明白,但这个文件的处理过程大概是这样的:
首先它包含了一个类来定义全局数据 ,主要是用来存储各个omx core library的索引,各个供应商的omx core以及相对应的component索引,这个全局数据提供了对所有的omx core的一个全局控制功能。
另 外它实现了所有的omx core method,比如说OMX_init,首先根据默认path读取所有的配置文件,然后根据配置文件的信息来载入所有的library,最后根据 library来对所有的omx core调用其相应的init进行初始化,然后对所有omx core下的所有component在PVMF中建立一个与omx core index相联系的一个registry。
再比如说当调用OMX_getHandle时,它首先会从registry中根据名字查找这个component,然后根据查找的component索引获得其OMX core的索引,再根据索引获得其相应的OMX_getHandle函数,再调用这个函数进行实例化。
通过上面的分析我觉得omx_mastercore.cpp它本身就是一个omx core,通过它来实现对所有具体omx core libray的管理 。】
3. Compiling the omx core library
因 为PVMF是通过使用动态载入和链接的方式来实现对多个omx core的同时处理的,因此所以的OMX core library都要编译成动态共享库,只要是以兼容的方式预先建立的动态共享库,都可以被载入和链接。(It is fine to incorporate pre-built libraries as long as it built in a compatible way as a shared object. 不知道这句话的意思我的理解对不对)
4. The OMX core library wrapper
根 据OMX spec编译出的core library除了要包含所有的method之外,还必须经过PV omx core wrapper的再一次封装,以使得PV opencore能够动态调用。有两种方式在最后的.so库中加入PV OMX wrapper,实际上也是共享数据库的两种调用方式。
一种方式就是对已经编译好的 omx core library,在PV omx wrapper中通过动态调用dlopen的方式载入,通过dlsym的方式来链接omx core method,这种封装方式的模板在:…/codecs_v2/omx/omx_core_plugins/template/src/
第 一种方式是在使用的时候动态地将library调入,然后链接,而第二种方式就是将omx core method和omx core wrapper interface放在一起编译成一个动态链接库。这种方式的模板在:…/codecs_v2/omx/omx_sharedlibrary /interface/src
这个模板的代办必须复制到供应商相应的目录以实现编译。
5. The configuration parser API
除 了标准的omx method之外,为了提高PV opencore的性能,PVMF要求omx core最好包含configuration parser API。因为PV opencore需要了解是否媒体剪辑是否为支持的类型,根据媒体类型来选择track和进行播放,但是因为PV opencore不了解component是否支持这样格式的编解码,或者说比如特定长宽的视频播放,如果由PV opencore来武断的决定的话,可能造成有些特性component不支持的PV opencore要求播放,而component支持的性能又被PVMF忽略了,所以这个工作最好来由omx core来实现。因此虽然这个API的实现是可选的,但是是强烈推荐实现的。
要实现 这个API,OMXConfigParser方法必须包含在OMX core内,OMX core wrapper会来链接这个函数,如果wrapper找不到”OMXConfigParser”这个符号,它就会使用默认的pv config parser(Ex参考pv_omx_interface.cpp中)
API的函数原型如下:
OMX_BOOL OMXConfigParser(OMX_Ptr aInputParameters, OMX_Ptr aOutputParameters) ;
输入参数的原型:
Typedef struct{
OMX_U8 * inPtr ;
OMX_U32 inBytes ;
OMX_STRING cComponentRole ;
OMX_STRING cComponentName ;
}OMXConfigParserInputs ;
inPtr:指向codec configureation header的指针
inBytes:codec configuration header的长度
cComponentRole:OMX component的编解码类型(比如说video_decoder.mpeg4)
cComponentName:OMX component name
role和name两个都必须具备,才能确定component的core,因为一个component可能具有多种role。
函数的返回值有两种,如果是OMX_FALSE的话,说明OMXConfigParser无法处理这样的codec configuration header,或者code format不是支持的类型。
如果函数返回OMX_TRUE,则函数必须对输出数据结构中的各项值进行赋值。
对于audio来说(使用指针类型实际中):
Typedef struct{
OMX_U16 Channels; //声道,比如mono或者stereo
OMX_U16 BitsPerSample;
OMX_U32 SamplesPerSec;
}AudioOMXConfigParserOutputs ;
对于video来说(使用指针类型实际中):
Typedef struct{
OMX_U32 width ;
OMX_U32 height ;
OMX_U32 profile ; //if applicable –-- detected clip profile
OMX_U32 level ; // If applicable --- detected clip level
}VideoOMXConfigParserOutputs ;
不管是输入数据还是输出数据的buffer都是在函数外部申请的。
C、Dynamic loading and registration of OMX cores
当所有的库都按照上面的步骤实现并编译好了以后,还需要一个额外的操作就是PVMF如何找到这些库,然后将库注册到PVMF上面。
要 让PVMF找到这些库,首先所有按照上面要求编译好的OMX core library都必须和一个唯一的接口(PVMF和OMX core通信的接口)ID (OSCLUuid)记录在一个配置文件(*.cfg)中。这些信息(library 和 OSCLUuid)可以放在一个已经存在的配置文件中,也可以放在一个新的配置文件中。如果是放在一个个新的配置文件中,则这个配置文件必须包含 ”.cfg”扩展名,并且必须放在android device的/system/etc目录下,并且这个文件中必须包含下面一行:
(OMX Core API OSCLUuid),”shared library name.so”
举个例子如下:
(0xa054369c, 0x22c5,0x412e,0x19,0x17,0x87,0x4c,0x1a,0x19,0xd4,0x5f),”libomx_core_vendorXXX.so”
注意:OsclUuid是OMX core interface唯一的API ID,是不能修改的。