1 OpenMAX IL介绍与其体系
这一部分的文档描写叙述 OpenMAX IL的特性与体系。
1.1 OpenMAX IL 简述
OpenMAX IL 软件接口层定义了一套API。用于訪问系统中的组件。OpenMAX IL软件层的目的:能够对系统中的组件採用不同的初始化值和不同的命令集合;同一时候还能提供一套统一的命令集合和方法来构建和销毁组件。
1.1.1 体系概览
考虑一个系统要实现四个多媒体处理功能模块,分别标记为 F1, F2, F3, 和F4。这四个功能模块中的不论什么一个都可能由不同的厂商或者同一个组织的不同部门所开发。每个功能模块的构建和销毁都可能有不同的要求。同一时候。每个模块的配置和传输数据都有不同的方式。 OpenMAX IL API能够将这些功能模块封装成一个组件,既能够每个模块一个组件或者在逻辑上相关的模块组成一个组件。
OpenMAX IL API提供一套标准的协议。能够让来自不同的厂商或者组织的组件互相交换数据。同一时候组件本身也可被还有一个组件替换。
与OpenMAX IL API通信的实体称之为IL client。 通常是多媒体框架或者应用层。IL client能够使用 OpenMAX core来载入和卸载组件。在两个组件之间建立通信机制和訪问组件的功能函数。
IL client通过IL core和组件之间进行通信。大多数情况下。IL client通过调用IL core所定义的宏来与组件通信,这些宏展开之后就直接调用一个组件的函数。例外情况是,IL client直接调用IL core的函数来载入和销毁组件,建立和撤销组件之间的隧道化连接。
组件代表着多媒体处理的一个单元或者多个单元的集合。虽然这份规范清晰的定义了OpenMAX core的功能。可是详细的功能还是由各个组件提供者负责实现。依据组件输出的參数数据类型的不同,把组件操作的数据类型分为四种:audio 数据。video数据 。image数据,和其它数据(比方时间或者同步数据)。
通过组件句柄能够訪问一个 OpenMAX 组件所提供的一系列标准方法。
这些方法同意client取得和设置组件以及组件中port的配置參数,取得和设置组件的状态,给组件发送命令。接收时间通知,分配buffer,和组件的一个port建立通信。以及在两个组件port之间建立通信。
一个OpenMAX组件必须至少有一个port,以满足 OpenMAX 的一致性标准。虽然厂商可能提供一个与OpenMax兼容的,不含有不论什么port的组件。可是大量的一致性測试都是基于组件含有至少一个port。 OpenMAX所定义的四种类型的port相应于port可能传输的四种数据类型。audio port。video port,image port和其它port。依据port是消费buffer还是生产buffer,能够把一个port分为input类型和output类型。
在一个包括F1,F2,F3,F4四个多媒体处理功能模块的系统中。系统实现者可能会为每个功能模块提供一个标准的OpenMax 组件,也能够简单的採取不论什么组合而提供一个组件。组件中的单独功能模块的区分就依赖于组件中的port。
图1-1展现了一些OpenMAX组件的实现方式:
图1-1 OpenMax组件的部分可能实现
1.1.2 关键词汇
本节讲述用于描写叙述OpenMAX IL API的经常使用缩略语和定义。
1.1.2.1 缩写
表1-1列出了描写叙述 OpenMAX IL API的经常使用缩写:
缩写词汇 |
含义 |
IPC |
处理器间的通信 |
OMX |
OpenMAX中的函数和数据结构的前缀。 比方一个组件可能处于 OMX_StateExecuting的状态 |
表1-1 缩写词汇
1.1.2.2 关键定义
表1-2 列出了用于描写叙述OpenMax API的关键定义:
关键词汇 |
含义 |
Accelerated component |
某一部分功能执行在加速器上的组件。加速组件有自己的特性,比方支持多种类型的隧道化 |
Accelerator |
用于加快某些功能处理速度的硬件 |
AMR |
adaptive multimedia retrieval的缩写,3GGP consortium中的一种adaptive multi-rate编码器 |
Host processor |
多核心系统中用于控制多媒体加速的处理器 |
IL client |
调用OpenMax core或者组件方法的软件层 |
Main memory |
host processor和accelerator所使用的外部内存 |
OpenMAX component |
包装有目标系统所要求的功能的组件 |
OpenMAX core |
与特定平台相关代码,用于定位和载入组件到主存中。同一时候core也负责从主存中卸载组件,当应用层指明这个组件不再须要的时候 |
Resource manager |
管理硬件资源的软件单元 |
RTP |
real-time protocol的简称,网络标准协议用于传输实时数据,包括音频和视频 |
Synchronization |
同步机制 |
Tunnels/Tunneling |
建立和使用一种标准的数据通道,这个数据通道直接被两个组件所管理。 |
表1-2 关键词汇定义
1.1.3 系统组件
图1-2描写叙述了OpenMAX所支持的多种类型的交流机制。每个组件能够有随意数目的port用于数据交换。仅仅有一个output port的组件称为source component;仅仅有一个input port的组件称为sink component;组件全部的功能执行在host processor上的称为host component;执行在accelerator上的组件称之为 accelerator component。OpenMAX既能够直接和应用层交流,也能够整合到多媒体框架中去。
接下来描写叙述三种通信机制。Non-tunneled communication 定义了在IL client和组件之间交换数据buffer的通信机制;Tunneling 定义了组件之间直接进行数据buffer交换的标准机制;Proprietary communication描写叙述了两个组件之间直接进行数据交流的机制,
1.1.3.1 Component Profile
OpenMax的组件依照功能分为两类:base profile 和 interop profile。
base profile的组件应该要支持non-tunneled的通信机制。
base profile可能支持proprietary communication机制。base profile组件不支持tunneled communication。
interop profile是base profile的超集。一个interop profile组件应该要支持non-tunneled和tunneled communication机制,可能支持proprietary communication机制
interop profile 和base profile最基本的不同点是前者支持tunneled communication机制。base profile的存在主要是为了简化OpenMax实现者的工作。
1.1.4 组件的状态
如图1-3 所看到的。一个组件可能要经历一系列的状态变化。如果每个组件的初始状态是unloaded。应用层通过调用OpenMax core的函数来载入组件。与组件之间的直接交流能够使组件变为其它的状态。
当状态变化的时候使用了无效的数据,组件可能会进入到 invalid state。
当IL cilent检測到组件处于invalid state的时候。应该对组件进行例如以下动作:stop, de-initialize, unload, reload。
图1-2描写叙述了从不论什么状态都能够变迁为invalid state,可是要想退出 invalid state仅仅有通过unload和reload组件。
图1-3 组件状态
当组件状态进入 IDLE state的时候可能会失败,由于在IDLE state下,必须为组件分配好全部的资源。
当从LOADED到IDLE转换失败的时候,IL client可能会重试一次,或者将组件的状态变迁为WAIT FOR RESOURCES 。当组件进入WAIT FOR RESOURCES状态。它便向厂商指定的资源管理单元注冊,一旦资源变为可用的时候。组件就会收到通知。资源管理单元随后将组件的状态变更为IDLE state。IL client向组件发送的命令控制着除INVALID state以外的其它状态的变化。
IDLE state状态表明组件已经拥有了全部它须要的资源。可是还没有開始处理数据。EXECUTING state表明组件准确接收buffer去处理数据,而且会调用相应的callback。当组件处于PAUSED state 状态的时候,组件保持着处理buffer数据的环境,可是没有处理数据或者交换buffer。
从PAUSED状态变化为EXECUTING状态将使组件从上次暂停的地方開始处理buffer数据。从EXECUTING或者PAUSED状态变化为IDLE状态,将会导致丢失buffer处理的环境。这就意味着数据流的处理開始点须要又一次指定。
从IDLE变化为LOADED将会导致失去可操作的资源,比方通信buffer。
1.1.4 组件体系结构
图1-4描写叙述了组件的体系结构。组件的入口点仅仅有一个(通过组件的详细来訪问一组标准函数),可是组件可能有多个向外的调用,这取决于组件有多少个port。
每个组件也会通过event handler来调用IL client的函数。
每个port也会发起对外部函数的调用。每个port都有一个与之关联的指向buffer header的指针队列。命令函数所发送的命令也在组件内部相应一个命令队列。全部的參数和配置调用。都有一个特有的index和与之关联的数据结构。
图 1-4 OpenMAX IL API组件体系结构
一个port必须支持callback调用到IL client,如果是支持interop profile 的组件,同一时候还要支持与其它组件的port之间的交流。
1.1.6 通信行为
一旦从 OpenMAX core接收到了组件的句柄,就能够完毕组件的配置工作。一旦组件的port配置完毕,每个port指定了其数据格式,而且组件进入合适的状态。就能够与组件进行数据通信调用了。这样的调用是非堵塞的。数据通信特定于组件的一个port。
IL client通过 OMX_EmptyThisBuffer函数来与Input port进行通信。
IL client通过OMX_FillThisBuffer函数来与output port进行通信。在同样的上下文实现中。OMX_EmptyBufferDone或者 OMX_FillBufferDone callback将会在IL client 调用函数返回之前被调用。
图1-5显示了同样上下文和不同上下文两种情况下对上述过程的不同实现。注意,IL client不要臆断组件的callback/return的时序。
图 1-5不同的上下文与同样上下文中不同的操作
和组件的数据通信一般直接发生在组件指定的port。
每个port都有一个它应该分配或者使用的组件自己定义的最小的buffer数目。一个port将一个buffer header与一个buffer关联。一个buffer header有成员指向了buffer中的数据,而且提供与buffer中内容相关联的元数据。每个组件port都应该有能力分配它自己的buffer,或者使用预先分配的buffer。
1.1.7 Tunneled Buffer的分配和共享
这节描写叙述tunneling component buffer的分配和buffer共享。对于一个tunnel,一个port提供buffer,它称为supplier port。然后把这些buffer传递给还有一个port,这个port称为non-supplier port。在最简单的情况下,supplier 负责分配buffer。然而,复杂点的情况下。 tunneling component能够选择复用另外一个组件port的buffer,以避免内存的拷贝和优化内存的使用。
这样的情况下称之为buffer分享。
不论什么两个port之间的一个tunnel。代表这两个port之间的依赖关系。buffer分享机制。扩展了这样的依赖,以便全部分享同一buffer集的port能够形成一条隐式的依赖链。准确的说。这条依赖链上的一个port分配buffer,其它的port共享这些buffer。
buffer共享在一个组件内实现,然后把这样的共享关系传递到另外一个组件。
一个non-supplier port不会知道supplier 组件的提供的buffer是自己分配的还是复用的此组件其它port上的buffer。更进一步说。supplier组件也不知道是否non-supplier组件会复用它所提供的buffer。
严格来说。一个组件仅有义务服从它所需的外部语义,而且能够实现这些语义背后的buffer共享。更详细的,外部语义要求一个组件做下面事情:
• 在它的全部supplier port上提供buffer。
• 准确的传达port 上 buffer的要求。
• 使用OMX_EmptyThisBuffer调用将一个buffer从output port传递到input port
• 使用OMX_FillThisBuffer函数调用将一个buffer从input port返回到output buffer。
如果一个组件选择共享buffer,那么它可能须要执行下面操作来满足这些要求:
• 在supplier port上提供复用的buffer。
• 当在port上传达buffer的要求时,准确的记下须要分享buffer 的port的数目
• 在内部使用OMX_EmptyThisBuffer函数调用将一个buffer从一个input port传递到output port,相应的会有一个 OMX_EmptyBufferDone 回调。
1.1.7.1 相关条款
这一节描写叙述在tunneled buffer分配和共享中用到的相关条款。图1-6展示了总的概念图:
图1-6 buffer分配和共享关系的样例
一对tunneling port,主动发起UseBuffer调用的是supplier port。一个 buffer supplier port 并不一定要分配buffer。它可能复用同一个组件内其它port的buffer。图1-6中 port a。c是 supplier port。接收相邻port 的UseBuffer函数调用的port,称之为 non-supplier port。图中b,d是 non-supplier port。
一个port的tunneling port是与之相邻的。共享同一条tunnel的port。port b是port a的tunnelping port。同样的,port a也是port b的tunneling port。
一个allocator port 是一个自己分配buffer的 supplier port。图中仅仅有port a是allocator port。
同一个组件中复用其它port的buffer的称之为 sharing port 。port c是一个sharing port。
至少使用了一条tunnel的组件称之为tunneling component。
一个port的 buffer requirement包括须要的buffer的数目和每个buffer的size。一个port通过在它的 tunneled port上调用 OMX_GetParameter。能够获得一个 OMX_PORTDEFINITIONTYPE数据结构,这个数据结构表示了buffer的requirement。
注意一个port也能够从共享它buffer的port获得buffer requirement而不用调用OMX_GetParameter。由于这两个port能够位于同一个组件内。
1.1.7.2 IL Client Component Setup
为了构建一个tunneling component。IL client 须要遵循下面步骤:
1.载入全部tunneling component,而且在这些组件之间建立tunnel;
2.给全部的组件发送命令,以便组件的状态从loaded state 变为idle state;
如果IL client不依照上述步骤执行。组件可能由于彼此之间的依赖关系而导致永远都不会进入到idle 状态。
1.1.7.3 共享buffer组件从Loaded转变为Idle State
在 OMX_SetupTunnel被调用的时候,将会确认一条tunnel的两个port中哪一个(input或者output)是buffer supplier。
因此当一个组件接收命令从loaded转换为idle的时候,它应该清晰的知道它全部的组件的角色:supplier或者 non-supplier 。
当接收命令从loaded转换为idle。组件按顺序执行下面操作:
1.组件确定採取拿一种方式实现buffer共享,遵循下面规则:
a) 组件能够复用buffer採取例如以下两种方式:复用一个input的buffer到一个或者多个output port上。或者复用一个output的buffer到一个input上。
b) 仅仅有 supplier port才干够复用还有一个port的buffer。
c) 当一个组件中有多个output port分享buffer的时候。port的buffer属性为仅仅读。
如图1-7 所看到的:
图1-7 同意的buffer分享关系
2.组件确定supplier port。以及哪些supplier port是allocator port。仅仅有当一个supplier port不复用同一个组件的non-supplier port的buffer的时候,它就是 allocator port。图1-8中,箭头背向的port是supplier port,箭头指向的port为non-supplier port。
一个port指出来的箭头表示共享关系。
带有盒子的port代表 allocator port。
3.一个组件依照下面操作给它的每个allocator port分配buffer:
a) allocator port确定 buffer requirement 依据每个复用buffer的port。參见下面的A
b) allocator port通过调用OMX_GetParameter来确认每个tunneled port的buffer requirement。
參见条款B
c) allocator port依据自己的buffer requirement,tunneled port的buffer requirement。以及sharing port的buffer requirement来确定应该分配buffer的最大数目。
d) allocator port告知与之tunneling的non-supplier port的实际buffer数目。通过调用 OMX_SetParameter函数,參数OMX_IndexParamPortDefinition,以此来设置nBufferCountActual的合适參数。
见条款E
e) allocator port 和每个与之关联的sharing port共享它的buffer。见条款D
f) 每个已经分配的buffer,allocator port都要调用OMX_UseBuffer来传递buffer到tunneling port。见条款C
一个组件应该满足下面条款:
A. 确定一个sharing port的requirement的时候。它应该首先在它的tunneled port上调用OMX_GetParameter查询requirement,然后返回它自己的requirements和查询所得的requirements的最大值。
B. 当 non-supplier port 接收 OMX_GetParameter调用。查询它的buffer requirements的时候,non-supplier port应该首先查询全部复用它的buffer的port的requirements。然后返回自己的requirements和查询到的requirements中的最大值。
C. 当一个 non-supplier port接收到它的tunneled port所发起的OMX_UseBuffer调用时。non-supplier port 应该给和自己所在组件的复用它buffer的port共享这个buffer。
D. 在同一个组件上。A和B共享一块buffer,当B复用这块buffer的时候,它应该首先调用 OMX_UseBuffer,把这块buffer传递给它的 tunneled port。
E. 当一个non-supplier port接收到来自它的tunneled port发起的针对OMX_IndexParamPortDefinition 的OMX_SetParameter 调用时。它应该把參数nBufferCountActual传递给不论什么复用它buffer的port。同样的。每个 supplier port通过这样的方式接收到 nBufferCountActual的时候,应该通过执行OMX_SetParameter (OMX_IndexParamPortDefinition)调用把 nBufferCount传递给它的 tunneled port。通过这样的方式,依赖链中实际使用的buffer的数目得以传递下去。
当全部enable的port都得到了他们所须要的buffer的时候。组件能够从loaded状态变为idle状态
1.1.7.4 使用共享内存的协议
当一个input port通过 OMX_EmptyThisBuffer接收一个共享buffer的时候。这个input port可能和一个output port通过下面机制共享这块buffer:
• 在input port 调用 OMX_EmptyBufferDone 作为对它的tunneling port的回复之前,output port在它的tunneling port上调用 OMX_EmptyThisBuffer。
• input port直到全部和它共享buffer的output已经分享了这块buffer之后才调用 OMX_EmptyBufferDone
1.1.7.5 不共享buffer组件从Loaded转变为Idle状态
如果组件不共享内存,比起共享组件的实现,将会降低非常多步骤和所遵循的条款。非共享内存组件从loaded转变为idle。依照下面步骤:
1.确定buffer共享实现的方式。
在这样的case下,不用进行这一步。
2.确定哪一些supplier port是 allocator port。全部都是。
3.依照例如以下步骤为每个 allocator port分配内存:
a. 由于没有共享内存,所以不用询问sharing port对buffer的要求;
b. allocator port 通过调用OMX_GetParameter来取得tunneled port对buffer的要求;
c. 依据allocator和与之关联的tunneling port的buffer requirement的最大值,来分配内存。
d. 由于没有内存共享。所以不用向sharing port传递buffer.
e. 对每一块分配的内存。allocator port 在tunneling port上调用 OMX_UseBuffer。
1.1.8 port重连
port重连同意一个tunneled 组件被还有一个tunneled组件替换,而不用破环其它的组件。在图1-10,组件B1被组件B2替换。
为了达到这点,组件A的output port和组件B的input port首先要通过port 禁止命令设置为不可用。一旦分配的buffer被返回给它们的拥有者并被释放。组件A的output port就能够连接到组件B2。接下来组件B1的output port和组件C的input port也要採取相似的方式禁用。当全部的分配的buffer都返回给它们的拥有者然后被释放,组件C的input port能够连接到组件B2的output port。全部的port能够被同意使用通过发送使能命令。
图1-10 port重连
在某些情况下,比方音频,当重连一个组件到还有一个组件的时候。可能希望新组件的数据採取fade-in的方式,而原始的组件的数据採取fade-out的方式(即淡入淡出)。图1-11 说明了这是怎样做到的。
第一步。组件A发送数据到组件B1。组件B1发送数据到组件C;组件A和组件C都有一个额外的port处于禁用状态。第二步,IL client首先为A和B2建立tunnel,然后为B2和C建立tunnel。然后使能两条tunnel上的全部port。如果组件C是audio组件。那么C就能够将组件B1和B2的数据採用变化的增益參数进行混合。在第三步。从组件A和C连接B1的port被禁用。
图1-11 重连组件
图1-11 重连组件
1.1.9 命令队列和buffer刷新
组件内独立的命令队列能够使组件刷新那些还没有处理的buffer,把它们归还给IL client,当採取 non-tunneled通信机制的时候,或者归还给与之关联的tunneled port。当採取的是tunneled通信机制。图1-12 如果组件有一个port使用了IL client分配的buffer。在这个样例中,client发送了5块buffer给组件,在发送刷新命令之前。
当组件处理刷新命令的时候。会依照原始的顺序把未处理的buffer返回给client。然后触发它的 event handler 发送event通知client。在接收到刷新命令之前,已经处理了两块buffer。连同为处理的三块buffer,组件会依照接收顺序,全部返还给client。
图1-12 刷新buffer
1.1.10 标记Buffer
IL client也能够通过标记buffer触发产生一个事件。
在一个buffer的buffer header中能够标记这块buffer。在OpenMax的组件链中,标记从一个input port传递到一个output port。标记同意一个组件发送一个事件给IL client。当这个组件遇到一个标记buffer。图1-13 解释了这个过程:
图1-13 标记buffer
IL client发送一条命令标记一个buffer。组件的output要发送的下一个buffer被标记,图中为B1。
组件B处理B1的数据,然后把结果填入到B2,同一时候还带上标记。
当组件C通过它的input port接收到B2。组件不会触发它的event handler,直到它已经处理完毕这块buffer。
1.1.11 事件和callback
组件发送给IL client 6种事件:
• 错误事件
• 命令处理完毕通知事件
• 标记buffer事件
• port设置变化通知事件
• buffer flag 事件,当遇到流的结尾
• 资源请求事件。当组件等待它所须要的资源的时候
1.1.12 Buffer Payload
port的配置定义了port上传输的buffer的数据格式,可是配置并没有说明数据在buffer中是怎样存放的。一般来说有三种case来描写叙述一块buffer怎样被数据填充,这三种case都有各自的优点。
在三种case中。buffer中有效数据的范围和起点由buffer header中的pBuffer。nOffset,和nFilledLength三个參数来决定。pBuffer指向buffer中有效数据的起始点。nOffset表示buffer 起始点到有效数据起始点的偏移量。nFilledLength表明有效数据的长度。因此buffer中有效数据位于 pBuffer +nOffset 到 pBuffer + nOffset + nFilledLength的范围内。
下面的case,描写叙述了在解码或者编码中,buffer中的压缩数据流进或者流出一个组件。在全部的case下,buffer仅仅是为数据的传递提供了一种机制。而对buffer中的内容没有特殊的要求。
对于数据的要求定义在port的配置中。buffer中的阴影部分表示数据,空白部分表示没有数据。
case 1:buffer被部分或者全部填充。在这样的case下。buffer中含有压缩数据帧,使用f1到fn来标记。
case 1为播放解码数据提供了便利。一个buffer能够含有多个帧。降低了为了达到解码所要求的数据量而导致的buffer传递的次数。然后。这样的情况下,须要decoder自己去buffer中解析帧数据。
同一时候组件须要有一个帧buffer,这个buffer中存放解析数据或者存放一部分的帧数据,由于完整的帧数据可能存在于下一个buffer中。
case 2 每个buffer中填充的是完整的帧。
case 2和case 1不同。由于case 1可能仅仅含有一帧的部分数据。
共同点都是须要解码器从buffer中分析出一块帧数据。
case 3 每一块buffer都仅仅含有一帧完整的数据。
case 3的优点是不须要解码器解析帧数据了,解析帧数据的工作放在了 source component。可是每次仅仅能传输一帧数据也可能会对性能造成非常大的冲击。
作为基本的要求。解码器或者编码器都应该支持case 1.
1.1.13 Buffer Flags和时间戳
Buffer flags 表示着buffer数据中的某些属性。
时间戳描写叙述着buffer中的数据在显示时候的时间信息。
一旦一个buffer的时间戳被 clock component组件所确定。不论什么的组件都不能为了速率控制或者同步而改动这个值。
Buffer中的元数据(即标志和时间戳)。适用于buffer中的第一个新的逻辑单元。
因此。对于一个buffer中含有多个逻辑单元。buffer的元数据适用于buffer起始边界以后的逻辑单元。除非另有说明,否则当一个组件接收到标记了flag或者时间戳的逻辑输入单元,它应该将这些元数据拷贝到逻辑输出单元中去。
1.1.14 同步
通过clock component的同步port能够到达同步的目的。
clock component和它的port被划分在 其它组件中。
clock component内部含有一个依据audio或者video的參考时钟来记录流媒体播放位置的多媒体时钟。clock component能够通过同步port传输带有时间信息的buffer到client 组件。
client组件可能给某个操作打上时间戳(比如一个视频帧的呈现),通过请求clock component发送时间戳信息,来匹配媒体时钟。图1-14 展示了这一过程:
1.1.15 速率控制
clock component通过提供一系列的配置来改变媒体时钟。以此实现全部的速率控制。IL client能够通过改变媒体时钟的比例系数(有效的改变媒体时钟变化的方向和速度),来实现播放,快进。暂停,后退,以及慢放。
IL client也能够通过这些配置来启动或者暂停媒体时钟。以此来改变媒体时钟的状态。
clock component通过在同步port上发送带有新的比例系数和媒体时钟状态的媒体时钟变化通知,来告知全部的client组件,媒体时钟的比例系数和状态发生了变化。虽然一个组件可能并不会以改变buffer的时间戳来应对媒体时钟比例系数的变化。可是它可能改变它相应的处理。
1.1.16 组件注冊
静态链接或者动态载入。
1.1.17 资源管理
这一节描写叙述OpenMax IL 中用于资源管理的API。
1.1.17.1 资源管理的必要
当一个组件由于缺少资源而不同意变迁为idle状态时。IL client没有必要知道缺少的资源,也没有必要知道是哪一个组件在使用这些资源。
OpenMAX的一个目标是通过提供IL 层。是IL 层以上的软件层与硬件无关。
通过指定下面这些关于资源管理的条款,以使OpenMax达到与硬件无关。
• 一个IL client没有必要知道IL 实现的细节或者IL 组件在使用哪一种资源
• 如果发生资源冲突,IL client能够依赖组件的一致行为而不用管IL的实现和详细的硬件平台
• 一个IL client不应该和硬件厂商的资源管理器直接交互,有下面两个原因:
• 和硬件无关原则相违反
• 和硬件资源管理器的详细工作大多数都是由IL client来处理,这会影响IL client在多种多媒体平台上的表现
虽然资源管理在 OpenMAX IL API 1.0版本号中解决,可是作为资源管理的“钩子”已经以行为准则。组件的优先级。资源管理相关的组件状态而落实。
这些钩子将会使在以后的版本号中全面解决资源管理奠定基础。
在继续之前,资源管理和政策的定义会使下面的讨论收益:
• Resource management负责组件訪问有限的资源。一个资源管理者要知道,当前有多少详细的资源可用,当前使用资源的组件,当前的组件使用了多少资源。一个资源管理器应该制定策略,当资源发生冲突的时候,哪一个组件能够优先使用。
• Policy 负责管理组件链。
依据 resource managemen提供的信息,或者系统配置,或者应用层的请求。或者其它的因素,策略管理者应该能够决定哪一个组件链能够执行或者恢复执行。
1.1.17.2 体系如果
下面有两种关于 OpenMAX IL层的体系如果:
如果1:在应用层和 OpenMAX IL之间存在一个framework层,包括有策略管理者。
如果2:一个系统可能有多个硬件平台供OpenMAX 组件使用,这些硬件平台由硬件厂商指定的资源管理者管理。
1.1.17.3 组件优先级
每个组件有一个由IL client设置的优先级(OMX_U32整形)。
详细的优先级的范围能够留给平台去实现,可是优先级的目的是非常重要的,而且能够在不同的IL 实现上表现一致。
组件的优先级依照数值从高到低越来越重要,0表示最高优先级。当两个组件拥有同样的优先级。近期被拥有过资源的组件被觉得具有较高的优先级。
1.1.17.4 行为规范
在IL 层定义了例如以下行为规范:
• 仅仅有当一个组件进入idle状态没有足够的资源或者一个组件不能释放占用的资源。将会产生OMX_ErrorInsufficientResources错误。
• 当组件进入idle状态的时候,它并不知道已经有人抢占了资源。或者低优先级的组件须要释放资源。
• 一个组件已经占领了的资源被抢占,当它从Executing或者Paused进入Idle的时候。要发送OMX_ErrorResourcesPreempted 给IL client,或者当它从Idle进入Loaded的时候,要发送 OMX_ErrorResourcesLost给IL client。
• 如果IL client想知道什么时候与组件相关的流能够启动或者恢复,它就应该请求得到一个通知,当组件的资源变为可用的时候。
当把组件的状态置为OMX_StateWaitForResources state,当资源可用,client就会收到通知。
1.1.17.5 硬件厂商相关的资源管理
为了实现上述规范,须要一个位于IL层之下与硬件厂商相关的资源管理者执行下面的功能:
• 实现管理等待队列
• 记录可利用的资源
• 记录使用资源的组件。以及他们使用的是什么资源
• 当一个高优先级的组件须要资源的时候通知一个或者多个组件释放他们所占用的资源