本文主要是介绍OpenMAX/IL: OMX IL 学习笔记【1】- 结构框架,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
本篇文章对OpenMAX做了一个整体的介绍与概述,说明OpenMAX是什么?可以解决什么问题?用在什么地方?以及为什么要用OpenMAX?这里并不对OpenMAX进行深入介绍(放到接下来的几篇文章里面),希望通过这篇文章可以对OpenMAX有一个大体的了解。
一、OpenMax简介
(1)什么是OpenMAX?
OpenMAX(Open Media Acceleration的缩写,开放多媒体加速器)是一个多媒体应用程序的标准。由NVIDIA公司和Khronos™在2006年推出。
它是无授权费的、跨平台的C语言程序接口序列,这些接口对音频、视频、静态图片的常用操作进行封装。
它包括三层,自上而下分别是应用层(AL)、集成层(IL)和开发层(DL)。
- OpenMAX AL:Application Layer,应用和多媒体中间层的标准接口,使得应用在多媒体接口上具有了可移植性。
- OpenMAX IL:Integration Layer,作为在嵌入式和移动设备中使用的audio,video,images codecs的底层接口。使得AP和多媒体框架可以以统一的方式访问多媒体codec和支持组件。Codec可以是硬件和软件的任意组合,对用户透明。
- OpenMAX DL:Development Layer,定义了一套API,包含了audio,video和imaging使用的函数集合,这些函数可以由芯片厂商针对新的处理器进行实现和优化,然后被codec 厂商在各种codec上使用。
这些层级之间可以相互组合实现,也可以单独实现某个层级,比如对于有些芯片厂商来说,他完全可以自己实现一套编解码硬件,然后在此基础上实现OpenMAX的IL层,这样使得基于该厂商硬件以及相关中间件开发的应用程序可以很快的移植到其它符合OpenMAX IL的软硬件设备上,同时其它平台的多媒体应用也可以无缝移植到该厂商的软硬件平台上面,而我们嵌入式软件岗在实际开发当中往往会去实现一个独立的OpenMAX IL层来承接编解码器与应用开发的桥梁。
其实,IL层已经成为了事实上的多媒体框架标准。 嵌入式处理器或者多媒体编解码模块的硬件生产者,通常提供标准的OpenMax IL层的软件接口,这样软件的开发者就可以基于这个层次的标准化接口进行多媒体程序的开发。
(2)OpenMAX可以用来做什么?
其实从名字上可以看出来,OpenMAX是与多媒体有关的,为多媒体处理提供统一的接口标准,以此来达到跨平台的多媒体软硬件开发的目标。在嵌入式设备比如安卓设备的多媒体软件框架中就使用到了OpenMAX编程标准。
一个完整的多媒体设备包括设备硬件、设备驱动以及设备应用程序。与之对应的是OpenMAX的DL、IL、AL层,不过在实际编程(嵌入式软件)当中最常使用到的是IL层。通过实现这三个层级,可以达到从硬件到软件的完整的音视频、图像等多媒体资源的编解码流程。
(3)为什么要使用OpenMAX ?
大概有这么几个理由促成了OpenMAX在多媒体编程当中的使用:
- 多媒体软件使用OpenMAX这一统一的编程标准来进行设计,可以使得开发者在开发应用等的时候不需要过度关注其底层的一些实现,也省去了大量的学习不同多媒体框架的时间。
- OpenMAX标准本身足够优秀,即使不完全遵循OpenMAX的标准来进行多媒体软件框架设计,采用OpenMAX的架构原理来作为多媒体软件框架的指导性设计原理,也能够大量减少多媒体软件的开发设计流程,并且由于OpenMAX本身的特点,也使得整个多媒体软件十分易于扩展,具有高度的去耦合性。该标准涵盖了大部分多媒体开发规格,可以轻松满足绝大多数开发需求。
- 该标准本身由多媒体等行业的领导者联合确立,具有较大的影响力,有相关的详细设计文档可以参考,如果遇到问题相对更加容易在网络上获取答案,并且整个标准在使用的时候无需授权费,是完全免费的。
(4)OpenMAX适用于哪些地方?
OpenMAX是专门用于音视频、图像编解码的,在一些以音视频编解码为主导功能的产品设计领域都可以使用OpenMAX,比如安防、手机(安卓系统里面就有OpenMAX)等。
其实综上就一句话,OpenMAX为整个多媒体编解码(从应用到硬件)流程提供了一个极度灵活的可移植的标准化解决方案。它解决的主要两个问题是:1. 提供完整的可实现的音视频、图像编解码流程;2. 使多媒体软硬件平台变得更加易于跨平台移植。
二、OpenMAX/IL: OMX IL - 结构框架
OpenMAX IL 层 API 旨在为媒体组件提供跨平台的可移植能力。这些接口将系统的软硬件结构进行抽象化。每个组件及其相关的转换都被封装在组件接口的内部。OpenMAX IL API 允许用户去加载,控制,连接以及卸载各独立的组件。这种极具灵活性的内核结构使得 Intergration Layer 能够很容易的实现几乎所有的多媒体应用情形,并且能够很好的与现有的基于图像的多媒体框架相结合。
1. 主要的功能和优点
OpenMAX IL API 能够在应用程序、多媒体框架和编解码库,以及其支持的组件(比如,sources 和 sinks)之间建立统一的接口。对于用户来说,组件自身及其内部的软硬件结合情况都是完全透明的。其主要功能如下:
- A flexible component-based API core;
- Ability to easily plug in new components;
- Coverage of targeted domains (audio, video, and imaging) while remaining easily extensible by both the Khronos Group and individual vendors;
- Capable of being implemented as either static or dynamic libraries;
- Retention of key features and configuration options needed by parent software (such as media frameworks);
- Ease of communication between the client and the components and between components themselves;
- Standardized definition of key components so all implementations of such “standard components” expose the same external interface (i.e. same inputs, outputs, and controls).
2. OpenMAX IL 软件结构
OpenMax的主要概念
客户端(Client):访问IL core或IL component的软件层,可能是位于GUI应用程序的下层,如GStreamer。IL client是一个典型的功能块,如filter graph multimedia framework,OpenMAX AL,或application都可以调用它。IL client与OpenMAX IL core进行交互,利用IL core加载和卸载组件、在组件间建立直接通信以及获得组件方法的入口。
core:相关平台的代码,具有将IL component载入主存储器的功能,当应用程序不再需要某组件时,IL core将负责把该组件从存储器卸去。一般来说,组件一旦载入存储器,IL core将不在参与应用程序与组件之间的通信。
端口(Port):组件的输入输出接口
组件(Component):OpenMax IL的单元,每一个组件实现一种功能。组件按照端口可分类为Source(只有一个输出端口)、Sink(只有一个输入端口)和Host组件(一个输入端口和一个输出端口),此外有一个Accelerator组件,它具有一个输入端口,调用了硬件的编解码器,加速主要体现在这个环节上。
隧道化(Tunneled):让两个组件直接连接的方式。通过隧道化可以将不同的组件的一个输入端口和一个输出端口连接到一起,在这种情况下,两个组件的处理过程合并,共同处理。尤其对于单输入和单输出的组件,两个组件将作为类似一个使用。
3. OpenMAX IL 接口
core API:负责动态加载和卸载组件,协助组件间通信。一旦加载组件,API 允许用户直接与组件进行通信,类似的,core API 允许用户在组件之间建立tunnel通信通道,一旦建立,core API 不再被需要,其通信直接发生在两个组件之间。
component API:在IL层,组件代表了独立的功能模块。一个组件可以是sources, sinks, codecs, filters, splitters, mixers, or any other data operator。各个组件的参数可以通过一组相关的数据结构,枚举类型和接口来设置或者获取。buffer状态,错误信息,以及其他的时间敏感信息会通过回调函数转发给应用程序。与组件进行数据的交换是通过端口(ports)完成的。 类似哦,组件间的tunnel通道也是通过将一个组件的输出端口连接到另一个组件的输入端口来建立的。
4. System 组件
OpenMAX IL 定义了三种通信方式:
1)Non-tunneled:用于client 与 component 之间交换data buffers;
2)Tunneling:用于组件之间互相交换data buffers的标准机制;
3)Proprietary communication:用于两个组件之间直接数据交换的专属机制,并且可以作为tunneling的备选机制。
openMAX IL的客户端,通过调用四个OpenMAX IL组件,实现了一个功能。四个组件分别是Source组件、Host组件、Accelerator组件和Sink组件。
- Source组件只有一个输出端口;
- Host组件有一个输入端口和一个输出端口;
- Accelerator组件具有一个输入端口,调用了硬件的编解码器,加速主要体现在这个环节上。Accelerator组件和Sink组件通过私有通讯方式在内部进行连接,没有经过明确的组件端口。
OpenMAL IL在使用的时候,其数据流也有不同的处理方式:既可以经由客户端,也可以不经由客户端。 图中,Source组件到Host组件的数据流就是经过客户端的;而Host组件到Accelerator组件的数据流就没有经过客户端,使用了隧道化的方式;Accelerator组件和Sink组件甚至可以使用私有的通讯方式。
OpenMAL IL的组件是OpenMax IL实现的核心内容,一个组件以输入、输出端口为接口,端口可以被连接到另一个组件上。外部对组件可以发送命令,还进行设置/获取参数、配置等内容。组件的端口可以包含缓冲区(Buffer)的队列。 组件的处理的核心内容是:通过输入端口消耗Buffer,通过输出端口填充Buffer,由此多组件相联接可以构成流式的处理。
5. Component profiles
OpenMAX IL 组件的功能被分成两种profiles:base profiles 和 interop profiles。
6. Component states
1)无效的数据会导致组件进入invalid状态;
2)在IDEL状态,组件应该获取了所有所需的静态资源;
3)在executing状态,组件不再接收buffer,而是进行处理数据;
4)在paused状态,组件维护一个buffer context,且不再处理数据和交换buffers;
7. Component 架构
OpenMAL IL中一个组件的结构如图:
在OpenMAX IL层中,一个重要的组成部分就是component,称之为组件,比如对于一个媒体播放器来说,它需要具有以下三个基本的功能:
- 音视频、字幕分离解析;
- 音频解码、视频解码;
- 音频输出、视频输出;
对于这三个功能来说,它们就可以拆分为5个组件,分别是:音视频、字幕分解组件;音频解码组件;音频输出组件;视频解码组件;视频输出组件;或许还需要字幕解析组件。而对于一个视频录制软件来说,它们这5个组件的功能恰巧相反,可以分为:音视频、字幕混合;音频编码;音频输入;视频编码;视频输入。
组件的功能和其定义的端口类型密切相关,通常情况下:
只有一个输出端口的,为Source组件;只有一个输入端口的,为Sink组件;有多个输入端口,一个输出端口的为Mux组件;有一个输入端口,多个输出端口的为DeMux组件;输入输出端口各一个的组件为中间处理环节,这是最常见的组件。
端口具体支持的数据也有不同的类型。例如,对于一个输入、输出端口各一个组件,其输入端口使用MP3格式的数据,输出端口使用PCM格式的数据,那么这个组件就是一个MP3解码组件。
通过上面的图可以看到,一个组件的大致结构有这么几点:
- 配置结构体(Parameter/Configuration Set/Get):用于用户代码直接与组件进行交互,包括组件属性设置获取、组件状态设置获取等。
- Port口:负责记录与之建立隧道链接的组件的信息,数据交流必不可少。
- Buffer管理:负责管理组件内部接收以及送出的数据流。
- 组件事件句柄(Component Event Handler):负责组件向用户代码进行事件通知,类似于Linux内核的Input子系统事件。
- 命令序列:负责存储并处理来自于用户代码产生的命令,比如状态转换等。
IL Clinet
顾名思义,IL Client就是指IL的客户端,可以在上图里面看到有IL Clinet的字样,对于组件来说,IL Client就是组件的管理者,Client通过组件内部提供的相关回调函数来对组件进行管理,应用程序可以调用Client的代码来操作组件,包括设置组件的状态、添加一个组件、销毁一个组件等等。
隧道链接
隧道化(Tunneled)是一个关于组件连接方式的概念。 通过隧道化可以将不同的组件的一个输入端口和一个输出端口连接到一起,在这种情况下,两个组件的处理过程合并,共同处理。尤其对于单输入和单输出的组件,两个组件将作为类似一个使用。
IL层的组件就是采用一种Tunnel(隧道链接)的方式来进行数据交流的,不同组件之间通过port进行相互链接,然后组件内部通过一个由IL层定义的方法来自行协调进行数据交流。整个链接过程是由组件的管理者连续调用两个组件的链接函数完成的,组件的链接函数里面会判断两个port是否适合链接,如果适合的话就将对方port以及COMP的句柄信息记录下来,存放到一个port结构体描述当中,这样的话两个组件就可以通过port来进行通信以及数据传输了。
8. Communication behavior
Client与component之间的通信:
client通过 OMX_EmptyThisBuffer
来调用component的输入端口;
client通过 OMX_FillThisBuffer
来调用component的输出端口。
9. Tunneled buffer allocation
对于tunnel的两个端口,supplier端口会调用UseBuffer函数来要求邻接的端口来处理buffers;non-supplier端口会接受UseBuffer调用。Component需要遵循以下规则:
1)supplier端口都要提供buffers;
2)在端口上可靠的传输buffer配置;
3)通过OMX_EmptyThisBuffer调用将buffer从输出端口传递到另一component的输入端口;
4)通过OMX_Fill_This_Buffer调用将buffer从输入端口返回给component的输出端口。
10. Buffer payload
一般情况下,buffer中可用数据的起始点和范围由定义在buffer头中的 pBuffer,nOffset 和 nFilledLen 三个参数来决定。pBuffer指向buffer的起始地址;nOffset代表了buffer起始地址与实际可用数据地址之间的偏移量;nFilledLen表示buffer中连续可用的数据的大小。因此,buffer中可用数据的起始范围分别为pBuffer + nOffset 和 pBuffer + nOffset + nFilledLen 。
在buffer中数据的存放方式有三种:
1)每个buffer要么填满,要么部分填满;
2)每个buffer中存放的压缩数据都是以完整的帧为单位的;
3)每个buffer中只存放一帧的压缩数据。
前两种都要求解码器在解码之前对每帧数据进行解析,第三种情况则不需要解析。
11. Buffer flags and timestamps
Buffer flags 是存放在buffer中的表示特定属性的数据,比如数据流结束;
Timestamps 是以微秒为单位的存放在buffer中的数据,用来在播放时确定各buffer的播放时刻。
12. OMX IL 示例结构
这篇关于OpenMAX/IL: OMX IL 学习笔记【1】- 结构框架的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!