分类: 嵌入式
2010-08-17 00:14:38
本文译自PV OpenCORE官方文档《OMX Core Integration Guide: OpenCORE
2.1, rev.1 Feb 25, 2009》。
在集成过程中,遇到的一个问题就是多个OMX cores的共存。它在linking和executing想要的OMX core方法时造成了问题。
第<1>节和第<2>节内容省略
<3>Building the OMX core library
<3.1>OMX core方法
PV OpenCORE提供PV OMX core和PV OMX组件的一个implementation。当与OMX core和其下的OMX组件通信时,PV OpenCORE框架相当于OpenMAX IL client。OMX core负责初始化、实例化OMX组件。必需通过提供OMX core以accompany待集成的OMX组件才能将OMX组件集成到OpenCORE框架中。换句话说,由于specified APIs以及PV OMX core和PV OMX组件之间的通信,vendors不应该试图将孤立的(isolated)OMX组件(without the accompanying OMX core)集成到已有的PV OMX core。在PV OMX core和PV OMX组件之间的这些APIs(初始化和实例化PV OMX组件)是内部的、特定执行的,而且OMX规范没有描述,随时会被PV改变。为了确保正确地实例化、注册和操作OMX组件,vendors应该提供并执行它自己的OMX core。
OpenMAX规范列出了以下9个属于OMX core的方法。这些方法都必须在库中提供,尽管并不需要完全支持。例如,如果仅支持OMX Base Profile,则必须在OMX core库中提供OMX_SetupTunnel方法,但可以简单地返回“OMX_ErrorNotImplemented”。
OMX_Init()
OMX_Deinit()
OMX_GetHandle()
OMX_FreeHandle()
OMX_ComponentNameEnum()
OMX_GetComponentsOfRole()
OMX_GetRolesOfComponent()
OMX_SetupTunnel()
OMX_GetContentPipe()
<3.2>多个OMX cores共存
隶属于不同厂商(vendor)的多个OMX cores共存的主要问题是所有的OMX cores必须执行同样的一套OMX core方法。如果只是简单地静态链接(statically linked)这些OMX cores就会导致link问题。一个简单(但十分不切实际)解决此link问题的方法是在每个厂商的OMX core库中重命名OMX方法已使能正确的link。
PV框架执行多个OMX cores的方法的动态装载和链接(loading/linking)。通过一个PV提供的瘦封装层(thin wrapper layer)来调用OMX core的方法。执行动态装载的代码存在于…/codecs_v2/oxm/omx_mastercore/…。这使得所有的OMX cores保持OMX core方法的命名成为可能。然而,这对被集成的OMX core库强加了某种需求。这些需求将在下面描述。
<3.3>编译OMX core库
因为PV OpenCORE框架利用动态装载和链接来处理潜在的多个OMX cores的同步,所以OMX core库必须被编译成动态对象。这意味着编译器标志必须被设置成位置独立码(position-independent code)。包含预编译的库是个很好的方式,只要预编译库被以兼容的方式编译成动态对象。
<3.4>OMX core库的封装
为了能让OpenCORE框架正确地动态装载,最终的共享库必须包含OMX core方法和OMX core封装方法。
目前,存在两种不同的方法能够将PV OMX core封装包含入最终共享库(.so)。
<
当单独编译包含OMX core方法的共享库时使用此方法,此时共享库中不包含OMX core封装。例如将这种库命名为“lib_prebuilt_omxcore_no_wrapper.so”。
必须单独将OMX core封装添加到库中以生成和构建新的共享库。新库中既包含“lib_prebuilt_omxcore_no_wrapper.so”,还包含OMX core封装接口。必须创建合适的makefile以拾取“lib_prebuilt_omxcore_no_wrapper.so”并添加OMX core封装来创建新共享库。
将新共享库命名为“lib_omxcore_plus_wrapper.so”。这是能被动态装载入OpenCORE的最终OMX core库。
OMX core封装接口示例代码:
…/codecs_v2/omx/omx_core_plugins/template/src
示例代码需拷贝到厂商代码目录的合适位置以生成“lib_omxcore_plus_wrapper.so”。
而且,示例行
#define OMX_CORE_LIBRARY “libOmxCore.so”
需要被下述代码行代替。这行代码包含预编译共享库的名字(此库只包含OMX core方法,但不包含OMX core封装)。
#define OMX_CORE_LIBRARY “lib_prebuilt_omxcore_no_wrapper.so”
作为动态装载过程的一部分,OMX core封装必须打开库“lib_prebuilt_omxcore_no_wrapper.so”并明确地将OMX core方法链接进这个库中(调用dlopen&dlsym)。
最终OMX core库的提供者(provider)必须确保生成此库(lib_omxcore_plus_wrapper.so)的makefile也包含OMX core库的封装。OMX core库封装器的目的是向PV OpenCORE框架提供共同的APIs以动态装载OMX core插件并与之通信。
<
生成有效共享库的第二个方法是同步编译包含OMX core方法和OMX core封装器接口的代码。
换句话说,在生成共享库时编译OMX core方法的makefile需要同时也编译OMX core封装器接口。在这种情形下,编译过程只生成一个共享库(称为“lib_omxcore_and_simultaneous_wrapper.so”)。此库能够被直接使用,并被动态装载进OpenCORE框架。
OMX core封装器接口的代码:
…/codecs_v2/omx/omx_sharedlibrary/interface/src
这些代码需要被拷贝到厂商代码目录的合适位置以生成“lib_omxcore_and_simultaneous_wrapper.so”动态库。
<3.5>配置解析器API
除了标准的OMX core方法之外,强烈推荐OMX core插件库还包含配置解析器APIs。为了优化性能,PV框架需要能够断定multimedia clip是否有效和被支持以完成track选择和开始回放。这个过程的效率非常重要。当涉及多个OMX core时,最好在实例化OXM组件和codecs之前完成这个断定。
为了方便检查,OMX core封装器和PV OMX core库执行一个API。这个API允许PV OpenCORE框架获得有关音频/视频track参数(例如宽度、高度或者抽样速率等)的信息和有关OMX组件和其下面的codec能否处理这个track的信息。基于获取的这些信息,PV OpenCORE框架将作出是否播放这个音频/视频track的决定。
注释:在OMX core插件库中的配置解析器API是可选的,然而,这是强烈推荐的。如果配置解析器API没有在OMX core插件中提供,PV OpenCORE框架将退回到PV执行的配置解析器API(fall back to the PV implementation of configuration parser API)。然而,因为这些APIs是为PV OMX组件配置的,这可能意味着可能选择了OMX core插件库不能播放的track,或者也可能意味着拒绝了可播放的tracks。
为了执行这些APIs,OMX core插件库(包含OMX core方法)需要提供“OMXConfigParser”方法。OMX core库封装器将链接到这个方法(“OMXConfigParser”)。如果封装器不能找到“OMXConfigParser”符号,它将使用PV默认的配置解析器。
此API定义如下:
OSCL_IMPORT_REF
OMX_BOOL OMXConfigParser(
OMX_PTR aInputParameters,
OMX_PTR aOutputParameters);
输入参数“aInputParameters”映射到:
typedef
struct
{
OMX_U8* inPtr; //pointer to codec configuration
header
OMX_U32 inBytes; //length of codec configuration
header
OMX_STRING cComponentRole; //OMX component
codec type
OMX_STRING cComponentName; //OMX component name
}
OMXConfigParserInputs;
参数
inPtr - 指向codec配置头部的指针
inBytes – codec配置头部的长度
cComponentRole – OMX组件codec类型(例如,“video_decoder.mpeg
cComponentName – OMX组件名称
注释:组件名和组件codec类型都需要作为参数。这是因为1)OHA框架需要能够认出组件隶属的确切的OMX core,和2)组件可能支持多个codec类型(role)。
返回值和输出参数有:
OMXConfigParser返回OMX_FALSE,如果它不能处理codec配置头部或者如果codec格式/类型(format/role)不被完全支持。
OMXConfigParser返回OMX_TRUE,如果它能处理codec配置头部。如果返回OMX_TRUE,也期待OMXConfigParser能填充“aOutputParameters”结构体。在音频codec的例子中,aOutputParameters映射到:
typedef
struct
{
OMX_U16 Channels;
OMX_U16 BitsPerSample;
OMX_U32 SamplesPerSec;
OMX_U32 SamplesPerFrame;
}
AudioOMXConfigParserOutputs;
在这里
Channels – 在音频track中检测到的信道数目(1-单声道 2-立体声)
BitsPerSample – 每个音频抽样的比特数(例如,16)
SamplesPerSec – track检测到的抽样速率
在视频codec的例子中,aOutputParameters映射到:
typedef
struct
{
OMX_U32 width;
OMX_U32 height;
OMX_U32 profile;
OMX_U32 level;
}
VideoOMXConfigParserOutputs;
Width – 检测到的输出视频clip宽度
Height – 检测到的输出视频clip高度
profile – 如果可用 – 检测到的clip profile
level – 如果可用 – 检测到的clip水平/高度/等级
注释:OMXConfigParser输入和输出结构体的存储空间是从外部分配的(例如,没有必要在OMXConfigParser方法的内部分配存储空间)。
<4>动态装载和注册OMX cores
还需要一个额外的步骤来注册OMX core插件库并将OMX cores动态装载到PV OpenCORE框架中。
OMX core库的名字(以上面论述的方式生成)连带独一无二的OsclUuid接口ID都需要记录到配置文件中。这个接口ID对应着用于与OMX core接口通信PV OpenCORE框架API。
将这些信息放到一个已经存在的配置文件(例如,pvplayer.cfg)中或者创建一个包含所需信息(OsclUuid & 库名)的配置文件都是可能的。如果创建了一个新的配置文件,那么这个配置文件必须有“.cfg”扩展名并且必须放在“/system/etc”Android设备目录中。无论哪一种方式,添加到*.cfg文件中的新行包括:
(OMX Core API OsclUuid), “shared library name.so”
例如,为了适当地注册和使用名为“libomx_core_vendorXYZ.so”的OMX core共享库(包含厂商的OMX core和PV OMX core封装器),必须在位于/system/etc目录下的*.cfg文件中添加下行:
(0xa
注释:提供的OsclUuid是独一无二的API ID,它设别OMX core接口,并且不能被修改:
(0xa
<5>数据格式的细节和OMX输出buffers