摘要:本文简要介绍了OpenMax的集成层,并阐述了其在Android上的实现和运行过程。

关键字:OMX,多媒体框架, IL, Android, Stagefright

1、OpenMax集成层介绍

OpenMax是一个多媒体应用程序的框架标准。它自上而下分为三层,Application Layer, Integration Layer和Development Layer。应用层规定了应用程序和多媒体中间层的标准接口,使应用程序的移植性更好。集成层定义了多媒体组件的接口,使得多媒体框架能以一种统一的方式访问多媒体Codec和组件,以便在嵌入式流媒体框架中快速集成加速编解码器。。开发层为Codec厂商和硬件厂商提供了一套API,使开发更加便捷。

OpenMax在Android上的实现_第1张图片

图1 OpenMax的分层结构

OMX集成层由Client、Core、Component和Port组成,Client通过Core得到对应Component的Handle,而后通过命令直接和Component进行交互。每个Component至少有一个Port进行数据交互,如Decoder有一个输入Port接收码流,一个输出Port输出YUV序列。Component内部可能通过消息处理机制完成Client要求的任务。

OpenMax在Android上的实现_第2张图片

图2 OMX IL层的组成

在Android中,OpenMax IL层,通常可以用于多媒体引擎的插件,Android2.2的多媒体引擎StageFright都可以使用OpenMax作为插件,主要用于编解码(Codec)处理。

在Android的框架层,定义了由Android封装的OpenMax接口,和标准的接口概念基本相同,使用C++类型的接口,并且使用了Android的Binder IPC机制实现了函数远程调用。Android封装OpenMax的接口被StageFright使用。

解码Component通过输入Port和输出Port来进行交互,可以通过和OMXCodec共享buffer来进行编解码。

OpenMax在Android上的实现_第3张图片

图3 StageFright的OMX结构

2、OMX相关的类关系

StageFright的核心播放器AwesomePlayer中包含了sp<MediaSource>型的mVideoSource指针,初始化时指向OMXCodec的实际对象。OMXCodec使用了Binder机制,实现了远程函数调用,且函数调用模式于本地函数无异,其中IOMX作为接口类定义了OMX的大部分接口函数。OMX的具体实现时,OMXMaster类用于管理OMX的插件,OMXNodeInstance类代表OMX的具体实例,完成和Component的调用和交互,内部类CallbackDispatcher是一个主动类,它用于调度处理回调函数传回的消息。OMXNodeInstance和CallbackDispatcher一一对应,协同工作,完成不同实例的消息处理。

OpenMax在Android上的实现_第4张图片

图4 OMX相关类关系图

OMXNodeInstance类中最重要的几个函数为:

allocateBuffer: Client通过调用此函数让Component分配Buffer。

useBuffer: Client通过此函数将已分配好的Buffer传给Component,让其使用。

freeBuffer: Client通过调用此函数让Component释放allocateBuffer()分配的Buffer。

fillBuffer: Client通过调用此函数传递空的Buffer给Component,让其将处理好的数据填入其中。此函数会调用OMX标准接口OMX_FillThisBuffer()。

emptyBuffer: Client通过调用此函数传递输入Buffer给Component,让其读取其中的数据进行编解码等处理。此函数会调用OMX标准接口OMX_ EmptyThisBuffer ()。

OnEmptyBufferDone: Component完成对输入buffer的读取后,调用此回调函数,向Client发送EmptyBufferDone消息。

OnFillBufferDone: Component完成相应处理将输出数据填入输出Buffer后,调用此回调函数,向Client发送FillBufferDone消息。

以Decoder为例,说明OMX Codec执行解码的过程,

OpenMax在Android上的实现_第5张图片

图5 OMX Codec解码序列图

OMXCodec使用emptyBuffer()函数(IL层中为OMX_EmptyThisBuffer()传递未解码的buffer给component,component收到该命令后会读取input port buffer中的数据,将其组装成帧进行解码,读取buffer中的数据完成后会调用EmptyBufferDone通知OMXCodec。

Compoment使用EmptyBufferDone消息通知OMXCodec已完成input buffer的读取,具体的实现是通过调用回调函数OnEmptyBufferDone()实现的。OMXCodec收到该命令后会通过mVideoTrack读取新的视频码流到input port的buffer中,并调用OMX_EmptyThisBuffer通知component。

OMXCodec使用OMX_FillThisBuffer传递空的bffer给component用于存储解码后的帧,Component收到该命令后将解码好的帧数据复制到该buffer上,然后调用FillBufferDone通知OMXCodec。

Compoment使用FillBufferDone通知OMXCodec已完成output port buffer的填充,具体的实现是通过调用回调函数OnFillBufferDone()实现的。OMXCodec收到该命令后将解码好的帧存入可显示队列中,AwesomePlayer调用OMXCodec::read()函数读出可显示队列的对头送给Renderer完成颜色转换等操作再传递给mISurface进行图像绘制,同时Render调用release()函数,其中的SignalBufferDone()会用OMX_FillThisBuffer通知component有空的buffer可填充。

更多相关文章

  1. Android bluetooth介绍(一):基本概念及硬件接口
  2. Android接口安全 - RSA+AES混合加密方案
  3. Android多媒体学习七:调用Android自带的音频录制程序,实现录制
  4. Android接口定义语言---AIDL(一)
  5. Android Apk反编译函数对应法则
  6. Android中的多媒体显示之图片缩放
  7. Android 的一些实用的函数
  8. android binder机制及其源码解析之第二节 重要函数讲解之常用数

随机推荐

  1. Android多点触控实现图片自由缩放
  2. 从Xamarin.Essentials谈Xamarin库的封装
  3. android的m、mm、mmm编译命令的使用简介
  4. Android开发必备偷懒神器之比例控件(正方
  5. Android画个时钟玩玩
  6. 【转】TextView实现文字滚动需要以下几个
  7. Android编程 系统资源的介绍
  8. Android中Activity的生命周期探讨
  9. 【Android(安卓)studio 解决过的问题】 N
  10. android 开发之切换landscape屏幕