Android Media Framework(三)OpenMAX API阅读与分析

android,media,framework,openmax,api · 浏览次数 : 0

小编点评

本文将重点介绍OpenMAX IL架构中的核心组件——OMX Core。OMX Core作为中间层,位于IL Client和实际OMX组件之间,为用户提供了一个管理OMX组件和处理组件创建的工具集。 1. OMX Core的位置与功能: OMX Core在OpenMAX IL架构中起到了桥梁的作用,连接了IL Client和实际的OMX组件。它为IL Client提供了两组API,一组用于管理OMX组件,另一组用于操作这些组件。 1.1 OMAP_Init与OMX_Deinit: OMX_Init用于初始化OMX Core,这在第一次使用OMX组件之前是必需的。初始化过程包括分配和初始化内存资源,扫描并加载系统中所有可用的OXM组件,并建立它们与OMX Core之间的连接。相应的,OMX_Deinit用于卸载OMX Core并释放相关资源。 1.2 OMX_ComponentName_ENUM: 这个API用于枚举OMX Core中所有可用的组件。它接受三个参数:组件名称的输出参数cComponentName,字符串长度的输入参数nNameLength,以及遍历OMX Core组件列表的索引nIndex。通过递增索引和多次调用此函数,可以实现组件的枚举。 1.3 OMX_GetHandle、OMX_FreeHandle、OMX_SetupTunnel、OMX_GetContentPipe: 这些API涉及创建、销毁和配置OMX组件。它们各自的参数包括组件句柄、组件名称、应用数据指针、回调函数,以及用于创建组件时参数的结构体和创建组件后参数的结构体指针。OMX_FreeHandle函数用于销毁组件,而OMX_SetupTunnel用于建立组件的输入/输出端口映射。 1.4 OMX_Get_components_of_role和OMX_GetRoles_of_component: 这些API用于检索特定角色和组件的列表。它们接受一个角色字符串和一个输出参数指针,后者用于存储组件数量。同时,输出参数指向一个含字符数组的指针,其中包含了组件名称。这两个函数的目的是提供有关特定角色及其支持的组件的详细信息。 总结: 本文全面概述了OMX Core的API,包括其位置、功能和使用方法。OMX Core在管理IL Client与实际OMX组件之间的交互方面发挥了关键作用,特别是在处理各种组件的初始化、创建、销毁和配置方面。通过学习和掌握这些API,开发者可以更有效地利用OMX Core,为音视频应用程序的开发奠定坚实的基础。

正文

这篇文章我们将聚焦Control API的功能与用法,为实现OMX Core、Component打下坚实的基础。

1、OMX_Core.h

OMX Core在OpenMAX IL架构中的位置位于IL Client与实际的OMX组件之间,OMX Core提供了两组API给IL Client使用,一组API用于管理OMX组件,另一组API用于操作/使用创建的OMX组件。

1.1

OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Init(void);
  • OMX_Init:OMX_Init用来初始化OMX Core,在第一次使用OMX组件前它需要先被调用,并且只被调用一次;初始化可能包含以下几个步骤:
    • 分配并初始化使用OMX组件所需的内存和资源;
    • 扫描系统中的所有可用OXM组件,并将它们加载到OMX Core中;
OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_Deinit(void);
  • OMX_Deinit:与OMX_Init功能相反,它用作于卸载OMX_Init加载的资源;
OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_ComponentNameEnum(
    OMX_OUT OMX_STRING cComponentName,
    OMX_IN  OMX_U32 nNameLength,
    OMX_IN  OMX_U32 nIndex);
  • OMX_ComponentNameEnum:用于枚举OMX Core中可用的所有组件,该API包含三个参数,第一个参数cComponentName用于返回找到的组件名称(输出参数),第二个参数是字符串的长度(输入参数),第三个参数是遍历OMX Core组件列表的索引,通过递增索引并反复调用这个函数,就可以枚举出OMX Core中所有的组件名称,该API有两个作用:
    • 当需要查看 OMX Core 中有哪些可用的组件时,可以使用这个函数来获取所有组件的名称;
    • 当需要通过名称来查找特定的组件时,可以使用这个函数来对所有组件进行遍历,直到找到与给定名称匹配的组件;
OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_GetHandle(
    OMX_OUT OMX_HANDLETYPE* pHandle,
    OMX_IN  OMX_STRING cComponentName,
    OMX_IN  OMX_PTR pAppData,
    OMX_IN  OMX_CALLBACKTYPE* pCallBacks);
  • OMX_GetHandle:用于创建一个OMX组件,返回的句柄就是我们前面学过的OMX_COMPONENTTYPE,该函数需要传递四个参数:
    • OMX_HANDLETYPE* pHandle:这是一个二级指针void**,用于接收创建的OMX_COMPONENTTYPE指针;
    • OMX_STRING cComponentName:组件名称,根据该名称创建对应的组件;
    • OMX_PTR pAppData:调用者(Application/IL Client)的指针;
    • OMX_CALLBACKTYPE* pCallBacks:给OMX_COMPONENTTYPE注册的回调函数,用于回传消息;
OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_FreeHandle(
    OMX_IN  OMX_HANDLETYPE hComponent);
  • OMX_FreeHandle:销毁创建的OMX组件,传入参数为OMX_HANDLETYPE hComponent
OMX_API OMX_ERRORTYPE OMX_APIENTRY OMX_SetupTunnel(
    OMX_IN  OMX_HANDLETYPE hOutput,
    OMX_IN  OMX_U32 nPortOutput,
    OMX_IN  OMX_HANDLETYPE hInput,
    OMX_IN  OMX_U32 nPortInput);

OMX_API OMX_ERRORTYPE   OMX_GetContentPipe(
    OMX_OUT OMX_HANDLETYPE *hPipe,
    OMX_IN OMX_STRING szURI);

这两个API Android中没有用到,暂不了解。

OMX_API OMX_ERRORTYPE OMX_GetComponentsOfRole (
    OMX_IN      OMX_STRING role,
    OMX_INOUT   OMX_U32 *pNumComps,
    OMX_INOUT   OMX_U8  **compNames);
  • OMX_GetComponentsOfRole:用于获取在给定role(角色)下可以使用的所有OMX组件的列表,包含三个参数:
    • OMX_STRING role:Role是用来描述OMX组件功能的字符串,每个OMX组件都拥有一个或多个角色,需要用role去指定OMX组件执行什么任务,role的名字规律"video_decoder.avc"、"audio_encoder.aac",第一个字段表示音频/视频,下划线后表示编码/解码,后缀表示具体的编解码类型;
    • OMX_U32 *pNumComps:输出参数,返回role对应的组件的数量;
    • OMX_U8 **compNames:输出参数,返回role对应的所有组件的名称
OMX_API OMX_ERRORTYPE OMX_GetRolesOfComponent (
    OMX_IN      OMX_STRING compName,
    OMX_INOUT   OMX_U32 *pNumRoles,
    OMX_OUT     OMX_U8 **roles);
  • OMX_GetRolesOfComponent:获取一个组件名对应的所有的Role,功能和OMX_GetComponentsOfRole类似;

根据OMX_Init和OMX_ComponentNameEnum等API中的描述,我们大致可以猜到,OMX Core中需要维护一个列表(map),列表中的内容是一组一组的Role和Component Name。

1.2

在OpenMAX IL框架设计中,IL Client不能直接访问OMX组件的函数,它需要调用OMX Core提供的宏来间接操作OMX组件。要注意的是,OMX Core没有为OMX组件的所有函数都提供宏,换言之有些OMX组件函数不是给IL Client使用的。

首先来看定义的宏:

#define OMX_SendCommand(                                    \
         hComponent,                                        \
         Cmd,                                               \
         nParam,                                            \
         pCmdData)                                          \
     ((OMX_COMPONENTTYPE*)(hComponent))->SendCommand(       \
         hComponent,                                        \
         Cmd,                                               \
         nParam,                                            \
         pCmdData)

OMX_SendCommand用于发送控制命令到组件,可用命令参考上文的枚举,该方法是非阻塞的,命令执行完成后需要发送callback通知IL Client。包含有四个参数:

  • hComponent:组件句柄;
  • Cmd:要发送的命令类型;
  • nParam:int类型的命令参数;
  • pCmdData:无法使用int表示的命令参数;
#define OMX_GetParameter(                                   \
        hComponent,                                         \
        nParamIndex,                                        \
        pComponentParameterStructure)                       \
    ((OMX_COMPONENTTYPE*)(hComponent))->GetParameter(       \
        hComponent,                                         \
        nParamIndex,                                        \
        pComponentParameterStructure)

OMX_GetParameter用于从组件获取参数设置,该方法为阻塞调用:

  • nParamIndex:参数索引,用来指定获取什么参数;
  • pComponentParameterStructure:指针,用于装载获取到的参数;
#define OMX_SetParameter(                                   \
        hComponent,                                         \
        nParamIndex,                                        \
        pComponentParameterStructure)                       \
    ((OMX_COMPONENTTYPE*)(hComponent))->SetParameter(       \
        hComponent,                                         \
        nParamIndex,                                        \
        pComponentParameterStructure)

OMX_SetParameter用于给组件设定参数,该方法为阻塞调用,参数功能与OMX_GetParameter类似。

#define OMX_GetConfig(                                      \
        hComponent,                                         \
        nConfigIndex,                                       \
        pComponentConfigStructure)                          \
    ((OMX_COMPONENTTYPE*)(hComponent))->GetConfig(          \
        hComponent,                                         \
        nConfigIndex,                                       \
        pComponentConfigStructure)

#define OMX_SetConfig(                                      \
        hComponent,                                         \
        nConfigIndex,                                       \
        pComponentConfigStructure)                          \
    ((OMX_COMPONENTTYPE*)(hComponent))->SetConfig(          \
        hComponent,                                         \
        nConfigIndex,                                       \
        pComponentConfigStructure)

OMX_GetConfig和OMX_SetConfig分别用于从组件获取配置、给组件设定配置,组件加载完成后可以
随时调用这两个方法,都是阻塞调用。不同于OMX_SetParameter设置的是组件的静态参数值,SetConfig设置的是运行时可更改的配置信息,例如视频的播放速度、音频的音量、视频的亮度等。

#define OMX_GetExtensionIndex(                              \
        hComponent,                                         \
        cParameterName,                                     \
        pIndexType)                                         \
    ((OMX_COMPONENTTYPE*)(hComponent))->GetExtensionIndex(  \
        hComponent,                                         \
        cParameterName,                                     \
        pIndexType)

OMX_GetExtensionIndex用于将OMX IL或厂商定义的扩展字符串转换为相应的结构体索引,该方法是阻塞的。许多音频和视频处理硬件具有特定的特性和特性,这些在OpenMAX IL标准中并未明确定义,为了使这些功能可以被利用,硬件厂商会提供特定的扩展;当应用程序需要访问这些特定的扩展功能时,就需要使用OMX_GetExtensionIndex来获取相关扩展的索引,然后使用这个索引去访问或者操作这些特定的扩展功能。

#define OMX_GetState(                                       \
        hComponent,                                         \
        pState)                                             \
    ((OMX_COMPONENTTYPE*)(hComponent))->GetState(           \
        hComponent,                                         \
        pState)

OMX_GetState用于获取组件的当前状态。

#define OMX_UseBuffer(                                      \
           hComponent,                                      \
           ppBufferHdr,                                     \
           nPortIndex,                                      \
           pAppPrivate,                                     \
           nSizeBytes,                                      \
           pBuffer)                                         \
    ((OMX_COMPONENTTYPE*)(hComponent))->UseBuffer(          \
           hComponent,                                      \
           ppBufferHdr,                                     \
           nPortIndex,                                      \
           pAppPrivate,                                     \
           nSizeBytes,                                      \
           pBuffer)

OMX_UseBuffer用于让组件使用由IL Client已经分配的buffer,或者使用tunneled组件已经提供的buffer。OMX_UseBuffer的实现应该分配出buffer header,并用参数填充它,最后通过ppBufferHdr返回。该方法是阻塞调用的,可以在LoadedToIdle状态下使用,也可在OMX_StateExecuting、OMX_StateIdle且端口被禁用的情况下使用。

关注公众号《青山渺渺》 获取更多音视频开发内容

image

与Android Media Framework(三)OpenMAX API阅读与分析相似的内容:

Android Media Framework(三)OpenMAX API阅读与分析

这篇文章我们将聚焦Control API的功能与用法,为实现OMX Core、Component打下坚实的基础。 1、OMX_Core.h OMX Core在OpenMAX IL架构中的位置位于IL Client与实际的OMX组件之间,OMX Core提供了两组API给IL Client使用,一组A

Android Media Framework(一)OpenMAX Spec阅读与框架简介

学习开源代码最快的方式是先阅读它的文档,再查看它的头文件,最后研读代码实现并进行编译调试。Android早期引入OpenMAX IL作为使用音视频编解码器的标准接口,了解Android Media框架的底层运行原理要从OMX IL开始。在这一节,我们将阅读整理OpenMAX IL Spec中的介绍和

Android Media Framework - 开篇

前言 Android Media是一块非常庞大的内容,上到APP的书写,中到播放器的实现、封装格式的了解,下到编解码组件的封装、VPU API的了解,每块内容的学习都需要我们下很大的功夫。此外,我们还要对相关的模块进行了解,比如AudioFlinger、SurfaceFlinger等,他们与Medi

Android 自定义带动画的柱状图

功能分析 假设要使用柱状图展示用户一周的数据,通用的做法是对接三方图表SDK或者自己通过代码绘制。 1、三方SDK通常包体较大,且定制性差,对特定的UI需求兼容性差; 2、自己绘制,比较复杂,而且要考虑各种兼容适配; 今天,我们使用一种简单的方式,来制作柱状图,不仅代码简单,而且支持UI样式、动画自

Android 屏幕适配

目录一、目的二、环境三、相关概念3.1 屏幕尺寸(screen size)3.2 屏幕分辨率(Resolution)3.3 像素(pixel)3.4 ppi3.5 dpi3.6 dp/dip3.7 sp四、Q&A4.1 为啥dpi = 160?4.2 为啥Android要引入dp概念?五、代码仓库地

有隙可乘 - Android 序列化漏洞分析实战

本文主要描述了FileProvider,startAnyWhere实现,Parcel不对称漏洞以及这三者结合产生的漏洞利用实战,另外阐述了漏洞利用的影响和修复预防措施,这个漏洞波及了几乎所有的Android手机,希望能带给读者提供一些经验和启发。

Android无障碍自动化结合opencv实现支付宝能量自动收集

Android无障碍服务可以操作元素,手势模拟,实现基本的控制。opencv可以进行图像识别。两者结合在一起即可实现支付宝能量自动收集。opencv用于识别能量,无障碍服务用于模拟手势,即点击能量。 当然这两者结合不单单只能实现这些,还能做很多自动化的程序,如芭芭农场自动施肥、蚂蚁庄园等等的自动化,

Android应用程序启动源码浅析-(三万字长文慎点&Android14)

在Android桌面Launcher源码浅析中介绍了Android的桌面程序Launcher是如何响应用户点击事件并启动App的,这篇文章继续介绍App在Android系统层的启动流程。 一、启动流程 sequenceDiagram participant User participant Laun

Android桌面Launcher源码浅析

在Android启动过程-万字长文(Android14)中介绍了Android系统的启动过程,本篇文章将继续介绍桌面应用Launcher。 一、Launcher介绍 在Android启动过程-万字长文(Android14)中提到Launcher是Android系统启动后,由SystemServerA

Android启动过程-万字长文(Android14)

在计算机启动过程和Linux内核Kernel启动过程介绍了计算机启动和内核加载,本篇文章主要介绍Android系统是如何启动的。 一、Android启动流程 Android系统的启动流程与Linux接近: sequenceDiagram participant Bootloader as 引导加载程