一 omx概述
OpenMax是一个多媒体应用程序的框架标准。它自上而下分为三层,Application Layer, Integration Layer和Development Layer。应用层规定了应用程序和多媒体中间层的标准接口,使应用程序的移植性更好。集成层定义了多媒体组件的接口,使得多媒体框架能以一种统一的方式访问多媒体Codec和组件,以便在嵌入式流媒体框架中快速集成加速编解码器。开发层为Codec厂商和硬件厂商提供了一套API,使开发更加便捷。
omx由组件构成:
1. 组件是独立的一个处理模块,可以有内部独立的线程(但并不一定)处理数据。 通常组件类型有:splitter组件、hot组件、sink组件、clock组件等。
2. 组件之间通过端口进行数据通信,每个组件至少要有一个端口,根据数据方向区分:有输入端口 和 输出端口 两种方向。任意一个端口只能是其中一种方向。
OMXMaster 负责OMX中编解码器插件管理,软件解码和硬件解码都使用OMX标准,挂载plugins的方式来进行管理。 软解通过 addPlugin(new SoftOMXPlugin)把这些编解码器的名字都放在PluginByComponentName。 硬件编解码是通过 addVendorPlugin(); 加载 libstagefrighthw.so.各个芯片平台可以遵循openmax 标准,生成libstagefrighthw.so的库来提供android应用。 android定义软编解码 /frameworks/av/media/libstagefright/omx/OMXMaster.cpp
高通定义 /QNX/qnx_ap/AMSS/multimedia/video/source/common/applications/qplayer/inc/OmxPlayer.h // OMX component name #define QCOM_DEMUXER_COMPONENT_NAME "OMX.qcom.file.demuxer" #define QCOM_IVRENDERER_COMPONENT_NAME "OMX.qcom.video.mmirenderer" #define QCOM_CLOCK_COMPONENT_NAME "OMX.qcom.mmiclock" #define QCOM_VIDEODECODER_COMPONENT_NAME "OMX.qcom.video.decoder" #define QCOM_VIDEODECODER_COMPONENT_NAME_AVC "OMX.qcom.video.decoder.avc" #define QCOM_VIDEODECODER_COMPONENT_NAME_MPEG4 "OMX.qcom.video.decoder.mpeg4" #define QCOM_VIDEODECODER_COMPONENT_NAME_H263 "OMX.qcom.video.decoder.h263" #define QCOM_VIDEODECODER_COMPONENT_NAME_WMV "OMX.qcom.video.decoder.wmv" #define QCOM_VIDEODECODER_COMPONENT_NAME_MPEG2 "OMX.qcom.video.decoder.mpeg2" #define QCOM_VIDEODECODER_COMPONENT_NAME_DIVX "OMX.qcom.video.decoder.divx" #define QCOM_VIDEODECODER_COMPONENT_NAME_DIVX311 "OMX.qcom.video.decoder.divx311" #define QCOM_VIDEODECODER_COMPONENT_NAME_VP8 "OMX.qcom.video.decoder.vp8" #define QCOM_VIDEODECODER_COMPONENT_NAME_SPARK "OMX.qcom.video.decoder.spark" #define QCOM_VIDEODECODER_COMPONENT_NAME_VC1 "OMX.qcom.video.decoder.vc1" #define QCOM_VIDEODECODER_COMPONENT_NAME_HEVC "OMX.qcom.video.decoder.hevc" #define QCOM_VIDEODECODER_COMPONENT_NAME_VP9 "OMX.qcom.video.decoder.vp9" #define QCOM_AUDIODECODER_COMPONENT_NAME "OMX.qcom.audiodecoder" #define QCOM_AUDIORENDERER_COMPONENT_NAME "OMX.qcom.audiorenderer" #define QCOM_RTPSOURCE_COMPONENT_NAME "OMX.qcom.rtpSource" #define QCOM_MPEG2TSDEMUXER_COMPONENT_NAME "OMX.qcom.demuxer.mpeg2ts" #define QCOM_VPP_COMPONENT_NAME "OMX.qcom.vpp" |
3. 端口根据通信的数据类型可以分为四种:Video_Port; Audio_Port; Image_Port; Other_Port; 其中除了音视频和图像数据,其他数据都是通过Other_Port来传递,比较典型的就是Clock全局时钟。
4. 每个组件都有自己独立的运行状态机,总共有6个状态。
OMX_StateInvalid : 组件运行中产生无法恢复的错误,不能再继续进行了,只能卸载组件
OMX_StateLoaded : 组件已经加载到系统中,但是还没有进行初始化
OMX_StateWaitForResources:组件正在等待资源,当资源到位后会切换成Idle状态
OMX_StateIdle:组件初始化完成,一切准备就绪
OMX_StateExecuting:组件正常运行,进行相关数据处理
OMX_StatePause:组件暂停运行
5. 组件支持两种不同的Profile:
1)Base Profile: 仅支持 non-tunnel方式的数据通信,也可能支持Proprietary模式
2)Interop Profile: 必须支持tunnel 和 non-tunnel两种数据通信方式,也可能支持Proprietary模式
OMX集成层由Client、Core、Component和Port组成,Client通过Core得到对应Component的Handle,而后通过命令直接和Component进行交互。每个Component至少有一个Port进行数据交互,如Decoder有一个输入Port接收码流,一个输出Port输出YUV序列。Component内部可能通过消息处理机制完成Client要求的任务。
图 StageFright的OMX结构
调用过程
二 omx用法
文件 | 描述 |
---|---|
OMX_Types.h | 数据类型,里面定义了组件类型、输入输出等 |
OMX_Core.h | IL层的核心API,有命令枚举、状态枚举、组件注册/初始化等等 |
OMX_Component.h | 组件相关的API,有端口类型与定义、组件回调函数成员定义等 |
OMX_Audio.h | 与音频相关的常量和结构体定义 |
OMX_IVCommon.h | 图像与视频通用的一些常量和结构体定义 |
OMX_Video.h | 视频相关的常量和结构体定义 |
OMX_VideoExt.h | 视频相关的常量和数据结构,是对OMX_Video.h的补充扩展 |
OMX_Image.h | 图像相关的常量和结构体定义 |
OMX_Other.h | 其它部分的结构体定义 (包含A/V同步) |
OMX_Index.h | OpenMAX定义的数据结构索引 |
OMX_IndexExt.h | OpenMax 定义的数据结构扩展索引 |
OMX_ContentPipe.h | 内容的管道定义 |
OMX_BUFFERSUPPLIERTYPE:用于组件内部端口数据流标识。
OMX_COMMANDTYPE:命令相关的枚举,用于Client对组件的命令控制。
OMX_STATETYPE:组件状态相关的枚举,用于组件状态标识。
OMX_ERRORTYPE:错误相关的枚举,类似于C库的错误状态集,用于标识组件内部或者Client的出错状态。
OMX_EVENTTYPE:事件相关的枚举,用于组件内部向Client发送事件通知。
1组件库函数:
1)OMX_CommandStateSet: 切换状态机
2)OMX_CommandFlush: 刷新缓冲区
3)OMX_CommandPortDisable:禁用某个端口
4)OMX_CommandPortEnable 启用某个端口
5)OMX_CommandMarkBuffer:标记缓冲区对象(如:仅解码)
这些命令执行完成后通过 EventHandler() 回调来通知完成
通过EmptyThisBuffer传递未解码的buffer给component,component收到该命令后会去读取input port buffer中的数据,将其组装为帧之后进行解码,buffer处理完成后会通过EmptyBufferDone通知上层输入使用完成,上层收到命令可以继续送输入帧流程。输出buffer方面,通过FillThisBuffer传递填充输出的空buffer给component,component在解码之后通过FillBufferDone通知上层输出填写完成,上层可以继续送待填充的输出帧流程。
2缓冲区对象
3组件通信方式
tunnel模式
与 Non-tunnel方式主要的差异就是:建立隧道后,组件之间的数据通信不需要IL Client参与了,两个组件内部直接进行。 通常支持Tunnel通信方式的组件都有内部线程,方便数据同步处理
non-tunnel模式
proprietary模式