Android 13 - Media框架(15)- OpenMax(三)

上一节学习了 media.codec 服务中的部分内容,这一节我们将一起了解 OMX IL 层的 API 以及相关的结构体等内容。

1、相关路径

以下是 Media 相关的头文件路径:
frameworks/native/headers/media_plugin/media/
cas 和 drm 是用于加密流解密使用,editor 里面有个 OMX_COLOR_FormatYUV420Planar 颜色空间的转换工具,这三个目录这里不做了解(不会),我们要重点关注的是 openmaxhardware 目录 。

1.1 hardware

frameworks/native/headers/media_plugin/media/hardware/
hardware 目录下放的是和硬件相关的一些头文件,CryptoAPI.h 大概是用于解密的,HDCPAPI.h 是用于HDMI加密的,这两个暂时不做了解;

OMXPluginBase.h 在前一节中已经做过了解了,libstagefrighthw.so 中的方法会创建一个 OMXPluginBase 对象;

VideoAPI.h 中声明有 media image (frame),以及 Aspects of color 等相关的结构体,这里不做过多描述。

1.1.1 HardwareAPI.h

以下内容部分翻译自 HardwareAPI.h 中的注释:

  • struct EnableAndroidNativeBuffersParams:这个结构体用于把android native buffer 用作 graphic buffer 和 secure buffer
    • graphic buffer usage:当 OMX node 通过 OMX_SetParameter 设定 OMX.google.android.index.enableAndroidNativeBuffers 配置时,这个功能将被打开(默认关闭);
      当某个端口的 native buffer 使用被禁止时,该端口将正常被使用,端口使用的 buffer 会用 UseBuffer 来设定,这是当 CPU 需要访问 buffer 时将使用的模式;
      当 native buffer 被启用时,视频的 color format 信息将会使用 Android pixel格式,而不是使用 OMX 格式。启用 native buffer 可能会改变 component 接收 buffer 的方式,如果 store-metadata-mode 被使能,那么将会以 metadata的形式传输。此外,除非支持 OMX.google.android.index.useAndroidNativeBuffer2 扩展,否则应该使用 OMX_SetParameter(UseAndroidNativeBuffer )来设定使用的 buffer。
    • secure buffer usage:当 OMX node 通过 OMX_SetParameter 设定 OMX.google.android.index.allocateNativeHandle 配置时,这个功能将被打开(默认关闭);
      当 native handle 在某个端口被禁用了,这个端口将会正常工作,并且预期调用 AllocateBuffer 来分配 buffer 并且返回 buffer 指针,这个模式会用作于 non-secure buffer 并且要组件分配 buffer 的情况;
      当 native handle 被使用时,组件需要分配一个 native_buffer_t 对象(可以通过binder传递),这个模式被用于 secure buffer,与之配合使用的有 nFilledLength、nAllocLength、nOffset 等参数。
    • 注释:之所以这个结构体放在 Hardware API中,我的理解是无论 graphic buffer 还是 secure buffer 都是由硬件分配管理的,上面的翻译中描述了两种模式成功应用和失败应用的情况,至于上层如何使用,后续我们将在 ACodec 章节中来学习。
  • struct StoreMetaDataInBuffersParams:这个结构体用于在 video source(camera…)和 video encoder之间,video decoder 和 output buffer 之间传递数据,而避免数据的拷贝。 meta data 在 OMX client 和 OMX component之间传递时,buffer中存储的并不是真正的 video 数据,而是一些用于定位/解析真正数据的信息。启动 meta data 时,bStoreMetaData 需要设置为 OMX_TRUE,默认情况下将会启用 meta data mode。
    当 bStoreMetaData 为 false 时,真正的 YUV 帧将会存储在 input/output buffer当中。
    Metadata buffer 需要使用 UseBuffer 来注册到 OMX component 中。
    • 当组件支援 OMX.google.android.index.storeANWBufferInMetadata 时,数据将会以 VideoNativeMetadata 的形式传递,并且会用 fence 来协同管理;
    • 当组件支援 OMX.google.android.index.storeMetaDataInBuffers 时,数据将会以 VideoGrallocMetadata 的形式传递。
    • 注释:之所以叫 meta data,指的是buffer中传递的不是真的数据,而是handle或者是物理地址,以及解析出buffer所需要的size、offset等信息,这些信息称为元信息,这个结构体一般会与上面的 grapgic buffer usage 搭配使用。
  • struct ConfigureVideoTunnelModeParams:用于 Android Tunnel Mode,网上讲 Tunnel Mode 的资料还比较少,具体如何实现不同的厂商可能有不同的方案,这里只翻译部分注释。
    • describe:如果 Tunnel Mode 被打开,那么 video decoder 解出的帧将会直接送到 sink(池子) 当中,nAudioHwSync 作为 HW SYNC ID 用来同步 audio hal 与 video 的输出,pSidebandWindow 需要绑定 codec 分配的 sideband window handle。

以上就是 HardwareAPI.h 中的部分内容,ACodec 并不会直接使用这些结构体,ACodec 回调用 IOmxNode 的接口,再由 OMXNodeInstance 解析参数,封装参数,最后传给 OMX component。

1.1.2 MetadataBufferType.h

这个文件中只定义了一个 enum MetadataBufferType,这里只对注释做一下翻译:

MetadataBufferType 定义了可以传递给 encoder 的 metadata buffer 的类型,这些类型主要是用于 libstagefright record框架使用的,这里的 record 可能指的是录屏或者是摄像头。Stagefright 框架是不需要知道关于 meta buffer的细节的,只要创建 meta buffer 和 video encoder 能够保持一致就行。

1.2 openmax

1.2.1 OMX_Core.h

这个文件应该算是 OMX 的入口了,文件一开始的注释:OMX_Core 头文件定了application 和 component 公用的内容,我的理解就是 OpenMax AL 和 IL 层之间的接口。

我们直接拉到文件末尾,可以看到一组函数声明,有心的小伙伴会发现我们在上一节的 QComOMXPlugin 中见过它们,这些方法会被封装在 libOmxCore.so 中,具体的内容需要 vendor 来实现,这里对这几个方法描述进行翻译:

函数参数里的OMX_OUTOMX_IN 用于记录当前的参数是返回参数还是输入参数。

  • OMX_Init:用来初始化 OMX core,这个方法执行时间应该小于 20 ms;
  • OMX_Deinit:对应于 OMX_Init,用于销毁 OMX core 中的内容,执行时间应该小于 20 ms;
  • OMX_ComponentNameEnum:枚举遍历系统中所有可用的编解码组件,第二个参数为一个字符指针,返回组件名称,名称类似于 OMX.qcom.video.decoder.h263;既然有遍历,那就会有一个容器来存储系统支援的所有组件信息,这个容器有各家vendor独立实现,实现不同会影响当前方法的实现;
  • OMX_GetHandle:根据给定的组件名称,将组件加载到内容当中(dlopen),调用组件的方法创建一个组件实例;(这里的意思是每个组件都是一个lib,每次要创建编解码实例都会dlopen,从而实现实例间互不影响,打开lib后会调用其中的方法返回示例,之后会直接使用这个实例,并且实例会被记录在 OMX core 当中);
  • OMX_FreeHandle:释放 component Handle;
  • OMX_GetRolesOfComponent:获取组件的 role;这里的 role 指的是什么呢?个人理解是这样:多个不同的编解码组件可能会走同一套流程,并不是我们所想象的每个组件都会单独编译出一个 lib,虽然说流程相同,但是内部的一些配置可能会不一样,为了区分当前使用的是哪一个组件,就用 role 来区分。

再往上看,又有一组函数声明,这组函数的命名和 struct OMX_COMPONENTTYPE 中定义的函数指针是一一对应的,我们之前有提到创建 OMX 组件后,我们并不是直接使用组件,而是将其封装到 OMXNode 当中,最终由 OMXNode 调用组件的方法,以下这组函数声明就是对调用组件方法的封装,第一个参数 hComponent 指的就是 handle component(组件句柄/指针):

  • OMX_GetComponentVersion:获取组件的信息,这是一个阻塞调用,耗时需要小于 5ms;
  • OMX_SendCommand:向组件发送一条命令,该调用是非阻塞的,组件需要先检查参数是否正确,然后才能将命令加入到组件线程中去执行,组件可能会调用 EventHandler callback 来返回结果,该函数的调用耗时需要小于 5ms;
    • 从这里我们可以知道,omx 组件中应该会有一个 component 线程来专门执行上层下发的命令;
    • 当命令是 OMX_CommandStateSet ,组件将会从 nParam 中获取新的状态,并且加入到命令队列中,从 executing 状态到 loaded 状态需要小于 500ms;
    • 当命令是 OMX_CommandFlush,组件将会强制把指定 port 上所有不在处理状态的 buffer 全部按照接收的顺序 return,每个 port 执行 flush 应该小于 5ms;
    • 当命令是 OMX_CommandPortDisable 或者是 OMX_CommandPortEnable,port 将会被关闭或者重启,耗时应该也小于 5ms;
  • OMX_GetParameter:获取当前组件的参数设置,它是阻塞调用,在 OMX_StateInvalid 状态下不能被调用,其他状态都能调用;它的第二个参数 nParamIndex 表示需要获取的参数类型,该方法执行时间应该小于 20ms;
  • OMX_SetParameter:类似 GetParameter;
  • OMX_GetConfig:从组件获取一个配置的结构体,这是一个阻塞调用,需要在 5ms 内完成;
  • OMX_SetConfig:给组件传递配置,需要与 GetConfig 搭配使用;
  • OMX_GetExtensionIndex:用于将 特定的vendor 配置或者参数翻译成为 OMX 结构体索引;
  • OMX_GetState
  • OMX_UseBuffer:请求组件使用一个已经分配的buffer(来自于另一个组件 或者 来自于上层),并且分配出组件自己的 buffer header,该调用应该在 5ms 内完成;
  • OMX_AllocateBuffer:请求组件分配一个新的buffer 和一个 buffer header,并且将 buffer header 的指针返回,该调用应该在 5ms 内完成;
  • OMX_FreeBuffer:组件将会释放调用创建的 buffer header,如果 buffer 也是组件创建的,那么也会释放掉该 buffer;
  • OMX_EmptyThisBuffer:将一块填有数据的 buffer 送给组件的 input 端口,这块 buffer 被清空时将会调用 EmptyBufferDone 回调,将 buffer 返回给应用层,这是一个非阻塞调用
  • OMX_FillThisBuffer:将一块空的 buffer 送到组件的 output 端口,组件将会填充该 buffer 并且调用 FillBufferDone 回传给应用层,同样的该函数也是非阻塞的
  • OMX_UseEGLImage

解下来再看看其他结构体:

typedef enum OMX_COMMANDTYPE
{OMX_CommandStateSet,    /**< Change the component state */OMX_CommandFlush,       /**< Flush the data queue(s) of a component */OMX_CommandPortDisable, /**< Disable a port on a component. */OMX_CommandPortEnable,  /**< Enable a port on a component. */OMX_CommandMarkBuffer,  /**< Mark a component/buffer for observation */OMX_CommandKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */OMX_CommandVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */OMX_CommandMax = 0X7FFFFFFF
} OMX_COMMANDTYPE;

command type 就是可以设置的命令类型,一般有状态设置,flush,端口的开启和关闭,vendor也可以自定义命令类型。

typedef enum OMX_STATETYPE

OMX_STATETYPE 指的是组件的状态,比较常见的有如下几种:

  • OMX_StateInvalid:组件发生异常;
  • OMX_StateLoaded:组件被创建但是还没有初始化完成;
  • OMX_StateIdle:组件初始化完成并且准备好开始;
  • OMX_StateExecuting:组件收到开始命令并且开始处理数据;
  • OMX_StatePause:组件收到暂停命令,这个用的很少

一些常见的flag:

  • OMX_BUFFERFLAG_EOS:EOS 表示输出端口将不会有数据再出来,所以在最后一块buffer上应该附上 EOS,上层给 decoder 写数据带上 eos 表示当前流结束;
  • OMX_BUFFERFLAG_STARTTIME:这个 flag 标记了起播时或者seek后第一帧应该从哪一帧开始显示渲染;比如说 seek 之后要从某个 pts 开始播放,但是刚好这一帧不是关键帧,那么需要从关键帧开始解码,从目标帧开始渲染。如果组件接收到 starttime,它应该调用 SetConfig 去设置 OMX_ConfigTimeClientStartTime
  • OMX_BUFFERFLAG_DECODEONLY:组件只解码不渲染;
  • OMX_BUFFERFLAG_DATACORRUPT:表示当前buffer中的数据存在错误;
  • OMX_BUFFERFLAG_ENDOFFRAME:表示当前buffer标志着一帧数据的结束,默认情况下Android每次写入都是一帧数据,所以每次数据写给 component 都会带这个flag;
  • OMX_BUFFERFLAG_EXTRADATA:额外的数据需要加在数据流之前,某些格式需要加一些数据头;
  • OMX_BUFFERFLAG_CODECCONFIG:codec specific data (csd),例如播放 h264需要的 SPS/PPS,播放AAC需要的AudioSpecificConfig,没有这些配置信息将无法解码播放。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/191256.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Elasticsearch 如何处理 Aggs 顺序中的大写字母和小写字母?

Elasticsearch 排序允许你根据特定条件对搜索结果进行排序。 然而&#xff0c;在排序时处理区分大小写时&#xff0c;Elasticsearch 将大写和小写字母视为不同的字符&#xff0c;分别对它们进行排序。 这是因为 ASCII 表顺序是从大写 A 到小写 z。 默认情况下&#xff0c;Elas…

6大关键词:尝新/随心/低忠诚···,全面解读食品饮料行业发展趋势与消费者洞察|徐礼昭

内容&#xff1a;重构零售实验室&商派 《2023食品饮料行业零售数字化洞察报告》节选 作者&#xff1a;徐礼昭&#xff08;商派市场负责人&#xff0c;重构零售实验室负责人&#xff09; 如今品牌的影响力不再止于资本与业绩数字&#xff0c;更多是在产品核心价值以及消费…

Xilinx FPGA平台DDR3设计详解(二):DDR SDRAM组成与工作过程

本文主要介绍一下DDR SDRAM的基本组成以及工作过程&#xff0c;方便大家更好的理解和掌握DDR的控制与读写。 一、DDR SDRAM的基本组成 1、SDRAM的基本单元 SDRAM的基本单元是一个CMOS晶体管和一个电容组成的电路。 晶体管最上面的一端&#xff0c;称作栅极&#xff0c;通过…

005、简单页面-容器组件

之——布局 目录 之——布局 杂谈 正文 1.布局基础知识 2.Column 3.Row 4.实践 杂谈 布局容器组件。 一个丰富的页面需要很多组件组成&#xff0c;那么&#xff0c;我们如何才能让这些组件有条不紊地在页面上布局呢&#xff1f;这就需要借助容器组件来实现。 容器组件是…

C语言中的格式化输出符号:%d %c %p %x等

文章目录 概览%d%c%d和%c的区别%p%x %X输出浮点数参考 概览 C语言中的格式化输出符号有很多&#xff0c;以下是一些常见的&#xff1a; %d 或 %i&#xff1a;用于输出十进制整数。 %u&#xff1a;用于输出无符号十进制整数。 %f&#xff1a;用于输出浮点数。 %s&#xff1a;用…

Android 13 - Media框架(19)- ACodec(一)

这一节我们将会了解 ACodec 的状态转换机制&#xff0c;从 ACodec 的基类名称HierarchicalStateMachine来看&#xff0c;它用到的是分层状态机&#xff0c;了解这里的状态转换将会对我们学习 OpenMax 会有所帮助&#xff0c;也会对我们自己的代码书写有所帮助。 1、AHierarchic…

通义千问 模型学习 和 SDK试用

通义千问-14B-Chat-Int4 模型库 (modelscope.cn) **通义千问-14B&#xff08;Qwen-14B&#xff09;**是阿里云研发的通义千问大模型系列的140亿参数规模的模型。Qwen-14B是基于Transformer的大语言模型, 在超大规模的预训练数据上进行训练得到。预训练数据类型多样&#xff0…

灯光开不了了,是不是NVIDIA的问题

如果你跟我一样灯光亮度调节不了了&#xff0c;然后显示适配器又没有了&#xff0c;你看一下是不是和我这个大怨种一样把NVIDIA卸了&#xff0c;为了这个东西&#xff0c;这屏幕亮瞎我的眼镜&#x1f622;&#x1f622;。只需要进入官网&#xff0c;你就可以直接找到&#xff0…

华为OD机试真题-来自异国的客人-2023年OD统一考试(C卷)

题目描述: 有位客人来自异国,在该国使用m进制计数。该客人有个幸运数字n(n<m),每次购物时,其总是喜欢计算本次支付的花费(折算为异国的价格后)中存在多少幸运数字。问:当其购买一个在我国价值k的产品时,其中包含多少幸运数字? 输入描述: 第一行输入为 k, n, m。 其中…

【el-form】表单label添加?及tooltip

<el-form-item><span slot"label"><el-tooltip :content"tooltip提示框内容" placement"top"><i class"el-icon-question"></i></el-tooltip>{{ $t(menu.status) }}</span><el-radio-gr…

某公司前端笔试题(12.30)

1、对象数组去重&#xff1a; 数组去重&#xff1a; const a[{a:1,b:2},{a:2},{a:2},{a:1,c:3},{b:2,a:1}] 结果&#xff1a;[{a:1,b:2},{a:2},{a:1,c:3}] // 判断两个对象的属性值是否一致 const a [{ a: 1, b: 2 }, { a: 2 }, { a: 2 }, { a: 1, c: 3 }, { b: 2, a: 1 }] co…

报错:执行sudo gedit时 No protocol specifiedUnable to init server: 无法连接: 拒绝连接

1.问题描述 在执行sudo gedit编辑文件时&#xff0c;报错连接不上服务&#xff1a; 2.问题解决 2.1先安装Vncserver sudo apt-get update sudo apt-get install tightvncserver2.2执行 vncserver 按提示输入密码&#xff0c;不宜过短 2.3若出现提示warning 则按提示执行&…

C#之扩展方法详解

前言&#xff1a; 我们想要向一个类型中添加方法&#xff0c;可以通过以下两种方式&#xff1a; 1.修改源代码。 2.在派生类中定义新的方法。 但是这两种方式都有缺点&#xff0c;1如果是别人的代码&#xff0c;你对其直接进行修改&#xff0c;可能破坏代码的完整性&#x…

Windows11系统下MemoryCompression导致内存占用率过高

. # &#x1f4d1;前言 本文主要是win11系统下CPU占用率过高如何下降的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;CSDN主页放风讲故事 &#x1f304;每日…

【STM32】TIM定时器

第一部分&#xff1a;定时器基本定时的功能&#xff1b; 第二部分&#xff1a;定时器的输出比较功能&#xff1b; 第三部分&#xff1a;定时器输入捕获的功能&#xff1b; 第四部分&#xff1a;定时器的编码接口。 1 TIM简介 TIM&#xff08;Timer&#xff09;定时器&#…

STM32GPIO速度配置究竟改变了什么-笔记

STM32GPIO速度配置究竟改变了什么-笔记 摘要STM32引脚内部框图STM32时钟树端口寄存器I/O交流特性定义 摘要 一般有 Low、Medium、High&#xff0c;三种速度选择。速度配置变了硬件什么状态&#xff1f; 对 GPIO 的输入输出信号有什么影响&#xff1f; 编程时如何选取速度参数&…

HNU-火星人足球赛

【问题描述】 火星人足球赛的比赛规则与地球人的比赛规则有些非常相似&#xff0c;比如严重犯规&#xff0c;将被给予黄牌警告&#xff0c;特别严重的犯规&#xff0c;将给予红牌直接罚下&#xff0c;如果有人得到第2张黄牌&#xff0c;则自动获得红牌罚下&#xff0c;比赛同样…

【哈希】两数之和

题目&#xff1a;https://leetcode.cn/problems/two-sum/description/?envTypestudy-plan-v2&envIdtop-100-liked class Solution {public int[] twoSum(int[] nums, int target) {Map<Integer, Integer> map new HashMap<>();for (int i 0; i < nums.l…

Oracle常见内置程序包的使用Package

Oracle常见内置程序包的使用 点击此处可跳转至&#xff1a;Oracle的程序包(Package)&#xff0c;对包的基础进行学习常见内置程序包的使用Package1、DBMS_OUTPUT包2、DBMS_XMLQUERY包3、DBMS_RANDOM包4、UTL_FILE包5、DBMS_JOB包6、DBMS_LOB包7、DBMS_SQL包8、DBMS_LOCK包9、DB…

【网络】传输层 -- 详解IP协议及IP协议的分片原理

目录 一、IP协议基本概念二、IP协议头格式1、报头和有效载荷如何分离2、有效载荷是如何向上交付&#xff08;分用&#xff09;的3、具体IP报头 三、网段划分1、什么是网段划分2、如何进行子网划分&#xff1f;再次理解子网划分及如何划分 3、私有IP地址和公网IP地址4、路由 四、…