Android 13 - Media框架(25)- OMXNodeInstance(二)
上一节我们了解了 OMXNodeInstance 的创建过程,以及 IOmx 服务和 OMXNodeInstance、OMX组件之间的联系。接下来我们将一起了解 ACodec 是如何通过 OMXNodeInstance 这个中间层进行端口定义设置,以及端口Buffer分配的。
OMXNodeInstance 的代码还是比较长的,我们需要重点抓住和 Buffer 相关的内容,也就是端口定义、Buffer分配以及 Buffer 传递,了解了 Buffer 那我们对 OpenMax 的学习就会很轻松了。
1、setPortMode
我们之前在学习 ACodec configureCodec 流程时看到有很多 portMode,端口类型确定之后就会调用 setPortMode 方法将端口模式设定给 OMXNode,最终设置给 OMX 组件。
status_t ACodec::setPortMode(int32_t portIndex, IOMX::PortMode mode) {status_t err = mOMXNode->setPortMode(portIndex, mode);if (err != OK) {ALOGE("[%s] setPortMode on %s to %s failed w/ err %d",mComponentName.c_str(),portIndex == kPortIndexInput ? "input" : "output",asString(mode),err);return err;}mPortMode[portIndex] = mode;return OK;
}
OMXNodeInstance 会根据设定的内容对 OMX 组件进行配置,我们这里暂时只研究解码的情况,一般解码流程可能会涉及到如下几种 port Mode:
in Port- non-secure:kPortModePresetByteBuffer,上层可以直接读写buffer;
- secure:kPortModePresetSecureBuffer,上层需要用特殊的方式读写buffer;
out Port- has native window
- tunnel mode:上层不需要接收 output buffer;
- non tunnel mode:kPortModeDynamicANWBuffer,使用动态的native window;
- no native window
- non-secure: kPortModePresetByteBuffer,上层可以直接读写buffer;
secure:error,不允许这种情况。
- has native window
1.1、kPortModePresetByteBuffer
之前我们讲过,Preset 是预设的意思,表示这块buffer是预先分配好的,之后使用过程中就不会发生变化了;ByteBuffer 指的是普通的buffer,我们通过指针就可以读写buffer中的内容。
kPortModePresetByteBuffer 会在两个情况下使用:
- 普通解码的 input buffer;
- 普通解码且无surface的 output buffer;
这两种情况下是可以通过指针读写 buffer 中内容的,也就意味着内容是不受保护的。
status_t OMXNodeInstance::setPortMode(OMX_U32 portIndex, IOMX::PortMode mode) {case IOMX::kPortModePresetByteBuffer:{// Disable secure buffer, native buffer and metadata.(void)enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_FALSE);(void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE);(void)storeMetaDataInBuffers_l(portIndex, OMX_FALSE, NULL);break;}
}
从注释中我们可以看出来,需要关闭端口的 secure buffer,native buffer以及metadata功能,这里的native buffer指的应该就是graphic buffer。
从这里我们可以猜测,OMX 组件端口使用的buffer可能有3种,默认使用普通buffer:
- 普通buffer;
- secure buffer;
- graphic buffer;
1.1.1、enableNativeBuffers_l
使用普通 buffer 就要把另外两个配置关闭,这里可以通过enableNativeBuffers_l方法来完成,之所以通过一个方法(并且方法名为 native buffer),是因为这些buffer本身都应该是由 native 层分配。由于OMXNodeInstance 把 secure buffer, graphic buffer的设置放到一起了,所以enableNativeBuffers_l容易把人看晕,把他拆成两部分:
先看 native buffer(graphic buffer)的配置部分,除了调用OMX_SetParameter对组件进行设定外,还将 mGraphicBufferEnabled 数组置为了 true/false,用于标记端口是否使用graphic buffer,如果使用了就置为true,没有使用就置为false。
OMX_STRING name = "OMX.google.android.index.enableAndroidNativeBuffers"EnableAndroidNativeBuffersParams params;InitOMXParams(¶ms);params.nPortIndex = portIndex;params.enable = enable;err = OMX_SetParameter(mHandle, index, ¶ms);CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d", name, index,portString(portIndex), portIndex, enable);if (err == OMX_ErrorNone) {mGraphicBufferEnabled[portIndex] = enable;} else if (enable) {mGraphicBufferEnabled[portIndex] = false;}
再看 secure buffer 的配置部分,secure buffer 对应的配置名称为 native handle,这是因为native层分配的buffer会以handle的形式回传上层,从而保护buffer。
OMX_STRING name = "OMX.google.android.index.allocateNativeHandle"EnableAndroidNativeBuffersParams params;InitOMXParams(¶ms);params.nPortIndex = portIndex;params.enable = enable;err = OMX_SetParameter(mHandle, index, ¶ms);CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d", name, index,portString(portIndex), portIndex, enable);if (!graphic) {if (err == OMX_ErrorNone) {mSecureBufferType[portIndex] =enable ? kSecureBufferTypeNativeHandle : kSecureBufferTypeOpaque;} else if (mSecureBufferType[portIndex] == kSecureBufferTypeUnknown) {mSecureBufferType[portIndex] = kSecureBufferTypeOpaque;}}
如果 secure buffer 设置成功,那么 mSecureBufferType 会被设置为 kSecureBufferTypeNativeHandle,否则置为 kSecureBufferTypeOpaque。
我们这里大概知道:
- secure buffer -> Native Handle;
- graphic buffer -> Native Buffer;
1.1.2、storeMetaDataInBuffers_l
除了以上两项配置外,还有额外的meta data type需要配置,我们前面了解过graphic buffer需要和metadata 搭配使用,但是metadata也有不同的类型,我们需要告知 OMX 组件使用哪一种 metaData,运行过程中OMX组件就会根据类型来解析metaData了:
status_t OMXNodeInstance::storeMetaDataInBuffers_l(OMX_U32 portIndex, OMX_BOOL enable, MetadataBufferType *type) {OMX_INDEXTYPE index;OMX_STRING name = const_cast<OMX_STRING>("OMX.google.android.index.storeMetaDataInBuffers");OMX_STRING nativeBufferName = const_cast<OMX_STRING>("OMX.google.android.index.storeANWBufferInMetadata");MetadataBufferType negotiatedType;// 如果参数type不指定具体类型,那么默认使用kMetadataBufferTypeANWBufferMetadataBufferType requestedType = type != NULL ? *type : kMetadataBufferTypeANWBuffer;StoreMetaDataInBuffersParams params;InitOMXParams(¶ms);params.nPortIndex = portIndex;params.bStoreMetaData = enable;// 接下来是尝试设置 meta data type,如果设置不成功就设置另外一种OMX_ERRORTYPE err =requestedType == kMetadataBufferTypeANWBuffer? OMX_GetExtensionIndex(mHandle, nativeBufferName, &index): OMX_ErrorUnsupportedIndex;OMX_ERRORTYPE xerr = err;if (err == OMX_ErrorNone) {err = OMX_SetParameter(mHandle, index, ¶ms);if (err == OMX_ErrorNone) {name = nativeBufferName; // set name for debuggingnegotiatedType = requestedType;}}if (err != OMX_ErrorNone) {err = OMX_GetExtensionIndex(mHandle, name, &index);xerr = err;if (err == OMX_ErrorNone) {negotiatedType =requestedType == kMetadataBufferTypeANWBuffer? kMetadataBufferTypeGrallocSource : requestedType;err = OMX_SetParameter(mHandle, index, ¶ms);}if (err == OMX_ErrorBadParameter) {err = OMX_ErrorUnsupportedIndex;}}
...else {if (!enable) {negotiatedType = kMetadataBufferTypeInvalid;}mMetadataType[portIndex] = negotiatedType;}if (type != NULL) {*type = negotiatedType;}return StatusFromOMXError(err);
}
storeMetaDataInBuffers_l 的代码比较长,主要是因为由两种meta data,一种是 kMetadataBufferTypeANWBuffer,另一种是kMetadataBufferTypeGrallocSource 。
默认情况下storeMetaDataInBuffers_l的第三个参数不填类型,默认使用 kMetadataBufferTypeANWBuffer,也就是于 graphic buffer 搭配使用的 meta data类型。设置的 meta data类型会被记录到 mMetadataType 中,后续还会使用到。
如果是用的普通 buffer (Byte Buffer),那么就不需要meta data了,mMetadataType会被设置为 kMetadataBufferTypeInvalid。
1.1.3、总结
综上:
当使用 Byte Buffer时,端口定义设置如下:
native handle(secure):disabled;native buffer(graphic):disabled;meta data:invaild;
1.2、kPortModeDynamicANWBuffer
有了上面内容的学习,设定端口为DynamicANWBuffer就很简单了:
case IOMX::kPortModeDynamicANWBuffer:{if (portIndex == kPortIndexOutput) {if (mLegacyAdaptiveExperiment) {CLOG_INTERNAL(setPortMode, "Legacy adaptive experiment: ""not setting port mode to %s(%d) on output",asString(mode), mode);err = StatusFromOMXError(OMX_ErrorUnsupportedIndex);break;}err = enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_TRUE);if (err != OK) {break;}}(void)enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_FALSE);err = storeMetaDataInBuffers_l(portIndex, OMX_TRUE, NULL);break;}
需要开启 grapihc buffer,关闭 secure buffer,使用 meta data,具体的端口设定如下:
native handle(secure):disabled;native buffer(graphic):enabled;meta data:kMetadataBufferTypeANWBuffer;
1.3、kPortModePresetSecureBuffer
secure buffer的设定同样很简单,需要关闭 grapihc buffer,开启 secure buffer,不使用 meta data,具体的端口设定如下:
native handle(secure):enabled;native buffer(graphic):disabled;meta data:invaild;
这里我们要注意的是,secure buffer是不需要meta data的。
case IOMX::kPortModePresetSecureBuffer:{// Allow on both input and output.(void)storeMetaDataInBuffers_l(portIndex, OMX_FALSE, NULL);(void)enableNativeBuffers_l(portIndex, OMX_TRUE /*graphic*/, OMX_FALSE);err = enableNativeBuffers_l(portIndex, OMX_FALSE /*graphic*/, OMX_TRUE);break;}
相关文章:
Android 13 - Media框架(25)- OMXNodeInstance(二)
上一节我们了解了 OMXNodeInstance 的创建过程,以及 IOmx 服务和 OMXNodeInstance、OMX组件之间的联系。接下来我们将一起了解 ACodec 是如何通过 OMXNodeInstance 这个中间层进行端口定义设置,以及端口Buffer分配的。 OMXNodeInstance 的代码还是比较长…...
生物系统学中的进化树构建和分析R工具包V.PhyloMaker2的介绍和详细使用
V.PhyloMaker2是一个R语言的工具包,专门用于构建和分析生物系统学中的进化树(也称为系统发育树或phylogenetic tree)。以下是对V.PhyloMaker2的一些基本介绍和使用说明: 论文介绍:V.PhyloMaker2: An updated and enla…...
XStream 反序列化漏洞 CVE-2021-39144 已亲自复现
XStream 反序列化漏洞 CVE-2021-39144 已亲自复现 漏洞名称漏洞描述影响版本 漏洞复现环境搭建 修复建议总结 漏洞名称 漏洞描述 在Unmarshalling Time处包含用于重新创建前一对象的类型信息。XStream基于这些类型的信息创建新实例。攻击者可以控制输入流并替换或注入对象&am…...
深入剖析LinkedList:揭秘底层原理
文章目录 一、 概述LinkedList1.1 LinkedList简介1.2 LinkedList的优点和缺点 二、 LinkedList数据结构分析2.1 Node节点结构体解析2.2 LinkedList实现了双向链表的原因2.3 LinkedList如何实现了链表的基本操作(增删改查)2.4 LinkedList的遍历方式 三、 …...
计算机网络复习-OSI TCP/IP 物理层
我膨胀了,挂我啊~ 作者简介: 每年都吐槽吉师网安奇怪的课程安排、全校正经学网络安全不超20人情景以及割韭菜企业合作的FW,今年是第一年。。 TCP/IP模型 先做两道题: TCP/IP协议模型由高层到低层分为哪几层: 这题…...
虚拟机服务器中了lockbit2.0/3.0勒索病毒怎么处理,数据恢复应对步骤
网络技术的不断发展也为网络威胁带来了安全隐患,近期,对于许多大型企业来说,许多企业的虚拟机服务器系统遭到了lockbit2.0/3.0勒索病毒攻击,导致企业所有计算机系统瘫痪,无法正常工作,严重影响了企业的正常…...
【MATLAB】 RGB和YCbCr互转
前言 在视频、图像处理领域经常会遇到不同色域图像的转换,比如RGB、YUV、YCbCr色域间的转换,这里提供一组转换公式,供大家参考。 色彩模型 RGB RGB色彩模型是一种用于表示数字图像的颜色空间,其中"RGB"代表红色&…...
【线性代数】决定张成空间的最少向量线性无关吗?
答1: 是的,张成空间的最少向量是线性无关的。 在数学中,张成空间(span space)是一个向量空间,它由一组向量通过线性组合(即每个向量乘以一个标量)生成。如果这组向量是线性无关的&…...
暴力破解(Pikachu)
基于表单的暴力破解 先随便输入一下,然后抓包,进行字典爆破 验证码绕过(on server) server服务端要输入正确的验证码后进行爆破 之后的操作没什么不一样 验证码绕过(on client) 这个也需要输入验证码,但是后面进行字典爆破的时候…...
如何使用CMake查看opencv封装好的函数
当我们有时想查看opencv自带的函数的源代码,比如函数cvCreateImage, 此时我们选中cvCreateImage, 点击鼠标右键->转到定义,我们会很惊讶的发现为什么只看到了cvCreateImage的一个简单声明,而没有源代码呢?这是因为openCV将很多…...
微盛·企微管家:用户运营API集成,电商无代码解决方案
连接电商平台的新纪元:微盛企微管家 随着电子商务的蓬勃发展,电商平台的高效运营已经成为企业成功的关键。在这个新纪元里,微盛企微管家以其创新的无代码开发连接方案,成为企业之间连接电商平台的强大工具。它允许企业轻松集成电…...
Hive 部署
一、介绍 Apache Hive是一个分布式、容错的数据仓库系统,支持大规模的分析。Hive Metastore(HMS)提供了一个中央元数据存储库,可以轻松地进行分析,以做出明智的数据驱动决策,因此它是许多数据湖架构的关键组…...
CopyOnWriteArrayList源码阅读
1、构造方法 无参构造函数 //创建一个空数组,赋值给array引用 public CopyOnWriteArrayList() {setArray(new Object[0]); }//仅通过getArray / setArray访问的数组。 private transient volatile Object[] array;//设置数组 final void setArray(Object[] a) {arra…...
Windows操作系统:共享文件夹,防火墙的设置
1.共享文件夹 1.1 共享文件夹的优点 1.2 共享文件夹的优缺点 1.3 实例操作 编辑 2.防火墙设置 2.1 8080端口设置 3.思维导图 1.共享文件夹 1.1 共享文件夹的优点 优点 协作和团队合作:共享文件夹使多个用户能够在同一文件夹中协作和编辑文件。这促进了团…...
STM32独立看门狗
时钟频率 40KHZ 看门狗简介 STM32F10xxx 内置两个看门狗,提供了更高的安全性、时间的精确性和使用的灵活性。两个看 门狗设备 ( 独立看门狗和窗口看门狗 ) 可用来检测和解决由软件错误引起的故障;当计数器达到给 定的超时值时,触发一个中…...
财务数据智能化:用AI工具高效制作财务分析PPT报告
Step1: 文章内容提取 WPS AI 直接打开文件,在AI对话框里输入下面指令: 假设你是财务总监,公司考虑与茅台进行业务合作、投资或收购,请整合下面茅台2021年和2022年的财务报告信息。整理有关茅台财务状况和潜在投资回报的信息&…...
vue3中使用three.js记录
记录一下three.js配合vitevue3的使用。 安装three.js 使用npm安装: npm install --save three开始使用 1.定义一个div <template><div ref"threeContainer" class"w-full h-full"></div> </template>可以给这个di…...
MySQL——表的内外连接
目录 一.内连接 二.外连接 1.左外连接 2.右外连接 一.内连接 表的连接分为内连和外连 内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选,我们前面学习的查询都是内连接,也是在开发过程中使用的最多的连接查询。 语法: s…...
基于IPP-FFT的线性调频Z(Chirp-Z,CZT)的C++类库封装并导出为dll(固定接口支持更新)
上一篇分析了三种不同导出C++类方法的优缺点,同时也讲了如何基于IPP库将FFT函数封装为C++类库,并导出为支持更新的dll库供他人调用。 在此基础上,结合前面的CZT的原理及代码实现,可以很容易将CZT变换也封装为C++类库并导出为dll,关于CZT的原理和实现,如有问题请参考: …...
【C语言】指针
基本概念 在C语言中,指针是一种非常重要的数据类型,它用于存储变量的内存地址。指针提供了对内存中数据的直接访问,使得在C语言中可以进行灵活的内存操作和数据传递。以下是关于C语言指针的一些基本概念: 1. 指针的声明ÿ…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
黑马Mybatis
Mybatis 表现层:页面展示 业务层:逻辑处理 持久层:持久数据化保存 在这里插入图片描述 Mybatis快速入门 
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会
在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...
Python竞赛环境搭建全攻略
Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型(算法、数据分析、机器学习等)不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...
第八部分:阶段项目 6:构建 React 前端应用
现在,是时候将你学到的 React 基础知识付诸实践,构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段,你可以先使用模拟数据,或者如果你的后端 API(阶段项目 5)已经搭建好,可以直接连…...
jdbc查询mysql数据库时,出现id顺序错误的情况
我在repository中的查询语句如下所示,即传入一个List<intager>的数据,返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致,会导致返回的id是从小到大排列的,但我不希望这样。 Query("SELECT NEW com…...
