Android 13 - Media框架(14)- 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/180088.shtml

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

相关文章

python3: jieba(“结巴”中文分词库) .2023-11-28

1.安装 jieba库(Windows系统) 打开cmd.exe(命令提示符) ,输入 下面内容后回车, 完成jieba库安装 pip install -i https://mirrors.bfsu.edu.cn/pypi/web/simple jieba 2.例题: 键盘输入一段文本&#xff0c;保存在一个字符串变量txt中&#xff0c;分别用Python内置函数及jie…

java后端实现信息分页查询

java后端实现信息分页查询 需求分析 在一个页面展示大量的用户信息不便于观看&#xff0c;因此采用分页展示的方法。用户可以通过分页条自己选择查看的数量。可以用条件过滤一些信息&#xff0c;在查询的同时还需要分页展示 代码开发 流程&#xff1a; 页面发送ajax请求&…

项目七 熟练使用Vim程序编辑器与shell

项目七 熟练使用Vim程序编辑器与shell #职业能力目标和要求 1&#xff0c;学会使用vim编辑器。 2&#xff0c;了解shell的强大功能和shell的命令解释过程。 3&#xff0c;学会使用重定向和管道的方法。 4&#xff0c;掌握正则表达式的使用方法。7.1 熟悉使用vim编辑器 7.1.1 …

使用opencv将sRGB格式的图片转换为Adobe-RGB格式【sRGB】【Adobe-RGB】

在C中使用OpenCV将图像从sRGB格式转换为Adobe RGB格式&#xff0c;需要应用特定的线性转换矩阵。sRGB和Adobe RGB使用不同的色彩空间&#xff0c;这意味着它们在色彩表达上有所不同。通常&#xff0c;这样的转换涉及到对RGB颜色值的线性变换。 但是&#xff0c;需要注意的是&a…

羽隔已就之图像处理之BP神经网络入门

小y最近非常忙&#xff0c;这一年来&#xff0c;活很多&#xff0c;一直在加班、出差&#xff0c;也没好好休息过。最近在武汉出差一个多月了&#xff0c;项目逐渐完结&#xff0c;有点闲时间了&#xff0c;回首望&#xff0c;这一年设定的很多目标都没完成。 还记得&#xff0…

深入Rust的模式匹配与枚举类型

今天&#xff0c;我们将深入探讨Rust语言中的两个强大特性&#xff1a;模式匹配&#xff08;Pattern Matching&#xff09;和枚举类型&#xff08;Enums&#xff09;。这两个特性是Rust提供的核心工具之一&#xff0c;它们在处理多种类型的数据和复杂的逻辑控制中发挥着关键作用…

七、Lua字符串

文章目录 一、字符串&#xff08;一&#xff09;单引号间的一串字符&#xff08;二&#xff09;local str "Hello, "&#xff08;三&#xff09;[[ 与 ]] 间的一串字符&#xff08;四&#xff09;例子 二、字符串长度计算&#xff08;一&#xff09;string.len&…

技巧-PyTorch中num_works的作用和实验测试

简介 在 PyTorch 中&#xff0c;num_workers 是 DataLoader 中的一个参数&#xff0c;用于控制数据加载的并发线程数。它允许您在数据加载过程中使用多个线程&#xff0c;以提高数据加载的效率。 具体来说&#xff0c;num_workers 参数指定了 DataLoader 在加载数据时将创建的…

深度学习之图像分类(十五)DINAT: Dilated Neighborhood Attention Transformer理论精简摘要(二)

Dilated Neighborhood Attention Transformer摘要 局部注意力机制&#xff1a;例如滑动窗口Neighborhood Attention&#xff08;NA&#xff09;或Swin Transformer的Shifted Window Self Attention。 优点&#xff1a;尽管在降低自注意力二次复杂性方面表现出色&#xff0c; …

c 数组简介

我们都知道我们可以使用一个变量来存储单个值,但如果我们必须一次存储 100 个值,那么声明和初始化 100 个变量并不是一种优化的处理方式。为此,我们在 C 中使用数组来存储类似数据类型的数据。C中的数组分为一维数组、二维数组和多维数组。数组索引始终从 0 开始,以 size-1…

微服务知识大杂烩

1.什么是微服务? 微服务(Microservices)是一种软件架构风格,将一个大型应用程序划分为一组小型、自治且松耦合的服务。每个微服务负责执行特定的业务功能,并通过轻量级通信机制(如HTTP)相互协作。每个微服务可以独立开发、部署和扩展,使得应用程序更加灵活、可伸缩和可…

C++多线程学习(文章链接汇总)

参考引用 C11 14 17 20 多线程从原理到线程池实战代码运行环境&#xff1a;Visual Studio 2019 C多线程学习&#xff08;一&#xff09;&#xff1a;C11 多线程快速入门 C多线程学习&#xff08;二&#xff09;&#xff1a;多线程通信和锁 C多线程学习&#xff08;三&#xff0…

docker 安装elasticsearch集群

准备工作 docker 安装好&#xff0c;docker compose 安装好编辑好docker-compose.yml文件&#xff08;本文会提供&#xff09;生成elastic-certificates.p12密钥&#xff0c;与docker-compose文件在同一个目录&#xff08;本文会介绍生成方式&#xff09;准备elasticsearch配置…

Selenium 学习(0.17)——软件测试之测试用例设计方法——白盒测试——逻辑覆盖法(条件覆盖和条件判定覆盖)

条件覆盖 设计测试用例&#xff0c;使每个判断中每个条件的可能取值至少满足一次。 条件判定覆盖 通过设计足够的测试用例&#xff0c;满足如下条件&#xff1a; 所有条件的可能至少执行一次的取值 所有判断的可能结果至少执行一次 条件判定覆盖同时满足判定覆…

centos7.9 + gitlab12.3.0安装

本文在centos7.9操作系统上安装gitlab 12.3.0&#xff0c;gitlab官方最新的版本已经是16.6.0了&#xff0c;这里仍然安装12.3.0版本的原因是汉化包的最新版本是12.3.0&#xff0c;如果汉化包的版本和gitlab的版本不对应&#xff0c;会出现汉化他无法启动的现象。 1、安装依赖 …

基于Hadoop的异构网络协同过滤推荐算法设计

基于Hadoop的异构网络协同过滤推荐算法设计 基于Hadoop的异构网络协同过滤推荐算法设计 Design of Heterogeneous Network Collaborative Filtering Recommendation Algorithm based on Hadoop 目录 目录 2 摘要 3 关键词 4 第一章 引言 4 1.1 研究背景 4 1.2 研究意义 5 1.3 国…

Python 图形用户界面详解(GUI,Tkinter)

文章目录 1 概述1.1 TK&#xff1a;窗口1.2 官方文档 2 组件2.1 Label&#xff1a;标签2.2 Button&#xff1a;按钮2.3 Entry&#xff1a;输入2.4 Text&#xff1a;文本2.5 Radiobutton&#xff1a;单选框2.6 Checkbutton&#xff1a;复选框2.7 Canvas&#xff1a;画布2.10 Men…

深拷贝 浅拷贝 递归

浅拷贝指的是创建一个新对象&#xff0c;其中包含原始对象的引用&#xff08;指针&#xff09;&#xff0c;并没有真正将原始对象的数据复制到新对象中&#xff0c;因此新对象与原始对象共享部分或全部数据。 深拷贝指的是创建一个新对象&#xff0c;并递归地将原始对象的数据…

Shell条件变量练习

1.算数运算命令有哪几种&#xff1f; (1) "(( ))"用于整数运算的常用运算符&#xff0c;效率很高 [rootshell scripts]# echo $((24*5**2/8)) #(( ))2452814 14 (2) "$[ ] "用于整数运算 [rootshell scripts]# echo $[24*5**2/8] #[ ]也可以运…

目标检测YOLO系列从入门到精通技术详解100篇-【目标检测】特征点检测与匹配

目录 前言 算法原理 一、图像特征介绍 二、特征检测子 三、特征描述子