OMX IL Spec将API划分为Control API、Data API、Extension API,所谓Control API指的是IL Client用于控制组件的接口,包含调用OMX Core和OMX Component要用的接口与相关结构体,这一篇我们将重点阅读与Control API相关的宏、结构体与枚举。
OMX IL API由一组头文件定义,包含以下内容:
在Android中,OMX IL API放在 frameworks/native/headers/media_plugin/media/openmax
目录下,进入目录可以看到包含所有上述提到的文件,除此之外还多了几个Ext结尾的文件,比如OMX_AudioExt.h
、OMX_VideoExt.h
,与之相对应的要添加索引文件OMX_IndexExt.h
,Ext表示扩展,意为这是Android在OMX IL基础上扩展的内容。
OMX IL使用的基本数据类型存放在OMX_Types.h
中,里面有一些宏定义,枚举和结构体,这里我们挑一些比较常见的来阅读。
OMX IL API在函数声明中使用宏参数功能进行描述:
还有另外一个宏OMX_ALL
,用于选择相同类型下的所有内容,在端口选择中会用到这个宏,表示选择所有端口。
接下来是一组typedef定义的数据类型:
typedef unsigned char OMX_U8;
typedef signed char OMX_S8;
typedef unsigned short OMX_U16;
typedef signed short OMX_S16;
typedef uint32_t OMX_U32;
typedef int32_t OMX_S32;
typedef unsigned long long OMX_U64;
typedef signed long long OMX_S64;
typedef void* OMX_PTR;
typedef char* OMX_STRING;
typedef unsigned char* OMX_BYTE;
typedef OMX_PTR OMX_HANDLETYPE;
上篇文章中提到组件句柄,它使用的类型是OMX_HANDLETYPE,在这我们可以知道组件句柄就是一个void*
指针。
最后是一些枚举类型:
typedef enum OMX_DIRTYPE
{
OMX_DirInput, /**< Port is an input port */
OMX_DirOutput, /**< Port is an output port */
OMX_DirMax = 0x7FFFFFFF
} OMX_DIRTYPE;
Dir是Direction的缩写,表示方向,用于表示端口数据的流向。如果数据向组件流入,端口用OMX_DirInput描述,表示输入端口;相对的如果数据从组件流出,用OMX_DirOutput表示输出端口。
为了跨平台OMX IL用枚举定义了布尔类型:
typedef enum OMX_BOOL {
OMX_FALSE = 0,
OMX_TRUE = !OMX_FALSE,
OMX_BOOL_MAX = 0x7FFFFFFF
} OMX_BOOL;
OMX Core API主要用于动态加载卸载组件,调用组件方法,所有调用组件用到的参数枚举、结构体类型,加载卸载函数,组件调用函数都存放在OMX_Core.h。
OMX_COMMANDTYPE包含了OMX IL可能发送给OMX组件的所有命令:
typedef enum OMX_COMMANDTYPE
{
OMX_CommandStateSet,
OMX_CommandFlush,
OMX_CommandPortDisable,
OMX_CommandPortEnable,
OMX_CommandMarkBuffer,
OMX_CommandKhronosExtensions = 0x6F000000,
OMX_CommandVendorStartUnused = 0x7F000000,
OMX_CommandMax = 0X7FFFFFFF
} OMX_COMMANDTYPE;
Android中常用的有:
typedef enum OMX_STATETYPE
{
OMX_StateInvalid,
OMX_StateLoaded,
OMX_StateIdle,
OMX_StateExecuting,
OMX_StatePause,
OMX_StateWaitForResources,
OMX_StateVendorStartUnused = 0x7F000000,
OMX_StateMax = 0X7FFFFFFF
} OMX_STATETYPE;
OMX_STATETYPE定义了OMX组件的状态类型,Android中只用到了前四个:
由于Android用到的状态只有四种,所以我把组件状态转换图做了简化:
图中的 四个红色的状态并不是OMX IL的标准内容,所以在头文件中是找不到的,但是它们在spec中有所描述。组件做状态切换时可能要处理一些事务,事务处理完成后才能完成状态切换,红色状态描述的是处理事务的 中间过程。
组件连接IL Client的端口,端口中的buffer可由IL Client分配,调用OMX_UseBuffer将buffer传递给组件,也可由IL Client调用OMX_AllocateBuffer让组件来分配。
以上图为例,IL Client调用OMX_UseBuffer将buffer传递给OMX组件,OMX组件in port共享IL Client的buffer,in port获取到需要的资源;OMX组件out port由自己分配buffer,IL Client调用OMX_AllocateBuffer让组件分配出所要用的buffer,out port获取到需要的资源;当所有端口buffer获取完成,OMX组件即可进入Idle状态。
如果端口用于隧道模式,supplier port中的buffer可由自己分配,也可以复用其他buffer,简单来说我们并不在意供应端口的buffer是怎么来的;供应端口组件调用OMX_UseBuffer把buffer传递给非供应端口。
OMX_StateIdleToExecuting:Idle状态切换到Executing状态组件不需要做任何事,IL Client开始数据传输流程即可开始编解码流程。
OMX_StateExecutingToIdle:Executing状态切换到Idle状态时,组件需要把所有的buffer都归还给buffer所有者。在组件之间或是组件与IL Client之间,端口使用的buffer由谁提供,buffer的所有者就是谁。延用前面的例子,ExecutingToIdle状态下需要把in port所有buffer的所有权交给IL Client,同时out port需要收回所有buffer的所有权。
OMX_StateIdleToLoaded:在Idle状态切到Load状态时,要释放所有获取到的资源,buffer由谁分配则由谁释放,对应的buffer header也要销毁掉。
typedef enum OMX_EVENTTYPE
{
OMX_EventCmdComplete,
OMX_EventError,
OMX_EventMark,
OMX_EventPortSettingsChanged,
OMX_EventBufferFlag,
OMX_EventResourcesAcquired,
OMX_EventComponentResumed,
OMX_EventDynamicResourcesAvailable,
OMX_EventPortFormatDetected,
OMX_EventKhronosExtensions = 0x6F000000,
OMX_EventVendorStartUnused = 0x7F000000,
OMX_EventOutputRendered = 0x7F000001,
OMX_EventDataSpaceChanged,
OMX_EventConfigUpdate,
OMX_EventOnFirstTunnelFrameReady,
OMX_EventMax = 0x7FFFFFFF
} OMX_EVENTTYPE;
OMX_EVENTTYPE定义了所有OMX组件可以生成的事件类型,这些事件可以通过callback发送给IL Client,Android常用的事件如下:
以上是OMX IL定义的标准事件,Android还额外定义了如下事件: