openmax用法

     

一  omx概述

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

                                                          图 OpenMax的分层结构

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

  1. kComponents[] = {  
  2.     { "OMX.google.aac.decoder", "aacdec", "audio_decoder.aac" },  
  3.     { "OMX.google.aac.encoder", "aacenc", "audio_encoder.aac" },  
  4.     { "OMX.google.amrnb.decoder", "amrdec", "audio_decoder.amrnb" },  
  5.     { "OMX.google.amrnb.encoder", "amrnbenc", "audio_encoder.amrnb" },  
  6.     { "OMX.google.amrwb.decoder", "amrdec", "audio_decoder.amrwb" },  
  7.     { "OMX.google.amrwb.encoder", "amrwbenc", "audio_encoder.amrwb" },  
  8.     { "OMX.google.h264.decoder", "h264dec", "video_decoder.avc" },  
  9.     { "OMX.google.h264.encoder", "h264enc", "video_encoder.avc" },  
  10.     { "OMX.google.g711.alaw.decoder", "g711dec", "audio_decoder.g711alaw" },  
  11.     { "OMX.google.g711.mlaw.decoder", "g711dec", "audio_decoder.g711mlaw" },  
  12.     { "OMX.google.h263.decoder", "mpeg4dec", "video_decoder.h263" },  
  13.     { "OMX.google.h263.encoder", "mpeg4enc", "video_encoder.h263" },  
  14.     { "OMX.google.mpeg4.decoder", "mpeg4dec", "video_decoder.mpeg4" },  
  15.     { "OMX.google.mpeg4.encoder", "mpeg4enc", "video_encoder.mpeg4" },  
  16.     { "OMX.google.mp3.decoder", "mp3dec", "audio_decoder.mp3" },  
  17.     { "OMX.google.vorbis.decoder", "vorbisdec", "audio_decoder.vorbis" },  
  18.     { "OMX.google.vpx.decoder", "vpxdec", "video_decoder.vpx" },  
  19.     { "OMX.google.raw.decoder", "rawdec", "audio_decoder.raw" },  
  20.     { "OMX.google.flac.encoder", "flacenc", "audio_encoder.flac" },  
  21. };  

高通定义         /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.hIL层的核心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.hOpenMAX定义的数据结构索引
OMX_IndexExt.hOpenMax 定义的数据结构扩展索引
OMX_ContentPipe.h内容的管道定义
  • OMX_BUFFERSUPPLIERTYPE:用于组件内部端口数据流标识。

  • OMX_COMMANDTYPE:命令相关的枚举,用于Client对组件的命令控制。

  • OMX_STATETYPE:组件状态相关的枚举,用于组件状态标识。

  • OMX_ERRORTYPE:错误相关的枚举,类似于C库的错误状态集,用于标识组件内部或者Client的出错状态。

  • OMX_EVENTTYPE:事件相关的枚举,用于组件内部向Client发送事件通知。

1组件库函数:

       

  1. IL层支持的库函数主要有两组:一组是针对所有组件库的Core函数; 另外一组是针对单个组件的函数。
  2. 大部分的函数操作都是同步调用,并且严格限制函数的执行时间(例如:OMX_SetConfig 限制在5ms内;OMX_UseBuffer 限制在20ms内)。
  3. OMX_FillThisBuffer() 和 OMX_EmptyThisBuffer()是异步调用,组件在实际执行完成后通过 EmptyBufferDone() 和 FillBufferDone() 两个回调通知执行完成。
  4. OMX_SendCommand() 函数也是异步调用,支持5种命令调用

        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模式

  1. IL Client通过OMX_AllocateBuffer() 在组件A的输出端口上创建缓冲区对象,这个缓冲区对象直接返回给 IL Client。
  2. IL Client再将这个缓冲区对象,通过 OMX_UseBuffer()指定给组件B的输入端口使用这个缓冲区对象。
  3. IL Client调用 OMX Core的 OMX_SetupTunnel(hCompA, nOutPortIdx, hCompB, nInPortIdx) 函数来将两个组件的输入输出端口建立隧道通信方式。注:这个函数内部实现会调用两个组件的内部函数ComponentTunnelRequest()来传递组件本身的信息。
  4. Push数据方式:组件A数据准备完毕后,直接调用组件B上的 OMX_EmptyThisBuffer()方法让组件B取数据,组件B获取完数据后,将OMX_EmptyBufferDone()通知直接回调给组件A,通知组件A这个缓冲区已经清空,可以继续使用了。
  5. Pull数据方式:组件B需要数据的时候,直接调用组件A上的 OMX_FillThisBuffer()方法让组件A填充数据,组件A填充完成后,将OMX_FillBufferDone()通知直接回调给组件B,通知组件B这个缓冲区上数据可以使用了。

与 Non-tunnel方式主要的差异就是:建立隧道后,组件之间的数据通信不需要IL Client参与了,两个组件内部直接进行。 通常支持Tunnel通信方式的组件都有内部线程,方便数据同步处理

non-tunnel模式

  1. IL Client通过OMX_AllocateBuffer() 在组件A的输出端口上创建缓冲区对象,这个缓冲区对象直接返回给 IL Client。
  2. IL Client再将这个缓冲区对象,通过 OMX_UseBuffer()指定给组件B的输入端口使用这个缓冲区对象。
  3. 在循环的数据处理过程中,IL Client调用OMX_FillThisBuffer() 命令组件A将处理好要输出的数据填入这个缓冲区中,注意:这个调用是异步的,这个调用返回后,缓冲区数据可能还没有填充好。
  4. 组件A内部先进行数据处理,处理完成后将输出数据填入缓冲区,然后通过 OMX_FillBufferDone()回调函数通知IL Client数据已经准备好。
  5. IL Client接收到回调后,调用OMX_EmptyThisBuffer()命令组件B来取缓冲区中的数据,注意:这个调用也是异步的,这个调用返回后,缓冲区数据可能还没有取走。
  6. 组件B内部根据优先处理顺序,将缓冲区中的数据全部取走后,然后通过OMX_EmptyBufferDone()回调函数通知IL Client缓冲区已经清空,可以继续使用。 如此反复来传递缓冲区对象,使得两个组件通过一个缓冲区来进行通信。
  7. 最后在组件A上释放这个缓冲区对象

proprietary模式

  1. 组件之间有类似DMA之类的直接通信机制,不需要外部提供缓冲区和控制缓冲区对象传递。
  2. IL Client 只需要调用 OMX Core的 OMX_SetupTunnel(hCompA, nOutPortIdx, hCompB, nInPortIdx) 函数来将两个组件的输入输出端口建立关联即可。
  3. 通常这种情况下的组件都是由硬件来实现,直接通过硬件或者系统内部的共享缓冲区来访问数据
  4. 通信时也不再有 OMX_FillBufferDone() 和 OMX_EmptyBufferDone() 的回调

  • 6
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 好的,OpenMAX是一种用于多媒体编解码和播放的跨平台API。下面是一个使用OpenMAX解码C语言的例子: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> #include "OMX_Core.h" #include "OMX_Component.h" #include "OMX_Types.h" #define H264_BUFFER_SIZE 512000 // 这是编解码器的名称,你可以使用OMX_ComponentNameEnum来枚举所有可用的编解码器 #define H264_DECODER "OMX.broadcom.video_decode" // 这些是编解码器需要的参数 #define INPUT_PORT 0 #define OUTPUT_PORT 1 // 这些是编解码器状态 #define STATE_INVALID 0 #define STATE_LOADED 1 #define STATE_IDLE 2 #define STATE_EXECUTING 3 // 这些是编解码器事件 #define EVENT_ERROR 0 #define EVENT_PORT_SETTINGS_CHANGED 1 #define EVENT_BUFFER_FLAG 2 // 这是编解码器的句柄 OMX_HANDLETYPE decoder = NULL; // 这是编解码器的状态 int state = STATE_INVALID; // 这是输入缓冲区 OMX_BUFFERHEADERTYPE* input_buffer = NULL; // 这是输出缓冲区 OMX_BUFFERHEADERTYPE* output_buffer = NULL; // 这是解码后的视频数据 uint8_t* video_data = NULL; // 这是解码后的视频数据的大小 int video_data_size = 0; // 这是解码后的视频帧的宽度 int video_width = 0; // 这是解码后的视频帧的高度 int video_height = 0; // 这是解码后的视频帧的帧率 int video_framerate = 0; // ### 回答2: OpenMAX是一套用于跨平台媒体组件的API标准,它提供了一种统一的接口,用于开发音视频处理应用。OpenMAX使用C语言编写,可以在多种移动设备、操作系统和处理器架构上运行。 开发OpenMAX解码的C语言demo可以按照以下步骤进行: 1. 首先,需要准备好OpenMAX库和头文件。可以从OpenMAX的官方网站或者相关实现商的网站下载并安装。 2. 在代码中包含OpenMAX的头文件,以便可以使用其中的函数和结构体。 3. 创建OpenMAX组件。使用函数OMX_GetHandle来获取组件的句柄,该句柄用于后续操作。 4. 配置组件的输入和输出端口。使用函数OMX_SetParameter来设置输入和输出端口的属性,例如输入数据格式、输出图像尺寸等。 5. 启动组件。使用函数OMX_SendCommand,并指定命令为OMX_CommandStateSet和OMX_StateExecuting,以启动解码操作。 6. 在解码过程中,通过回调函数接收解码后的数据。可以使用回调函数OMX_CALLBACKTYPE中的EmptyBufferDone和FillBufferDone来处理输入和输出缓冲区。 7. 解码完成后,释放资源。使用函数OMX_FreeHandle释放组件的句柄,使用函数OMX_Deinit来卸载OpenMAX库。 通过以上步骤,可以实现一个简单的OpenMAX解码的C语言demo。在具体实现过程中,可能还需要根据解码的具体要求进行一些额外的配置和处理。为了更好地理解和使用OpenMAX,建议参考相关的文档和例程,以便更好地了解和掌握OpenMAX解码的原理和操作方法。 ### 回答3: OpenMAX是一种多媒体编解码标准,可以用于实现音频和视频的编解码操作。在C语言中,我们可以使用OpenMAX库来编写相关的解码Demo。 首先,我们需要包含OpenMAX的头文件,并初始化OpenMAX组件。可以使用函数omx_init()来完成初始化操作。接下来,我们需要创建一个OpenMAX组件实例,可以使用函数omx_create_component()来创建。 创建完成后,我们需要设置组件的输入和输出端口。可以使用函数omx_set_input_port()和omx_set_output_port()来完成端口设置。然后,我们可以使用函数omx_allocate_buffer()为输入和输出端口分配内存,并设置端口的参数,比如缓冲区的大小和数据的格式。 接下来,我们需要加载媒体文件并将其数据送入输入端口。可以使用函数omx_fill_buffer()将数据写入输入端口的缓冲区中。然后,我们可以调用函数omx_empty_buffer()来启动解码过程。 解码过程中,我们需要循环处理输出端口的数据,直到解码完成。可以使用函数omx_read_buffer()从输出端口读取缓冲区的数据,并进行相应的处理。 最后,我们可以使用函数omx_deinit()来释放OpenMAX组件,并释放之前分配的内存。这样,我们就完成了OpenMAX解码的C语言Demo。 总结来说,OpenMAX解码的C语言Demo主要包括初始化组件、创建、设置输入和输出端口、分配内存、加载数据、启动解码过程、处理输出数据和释放资源等步骤。这个Demo可以作为学习和实践OpenMAX编解码的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

步基

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值