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. 指针的声明ÿ…...
深度掌握GB28181视频监控API:构建高效国标协议的3个核心技巧
深度掌握GB28181视频监控API:构建高效国标协议的3个核心技巧 【免费下载链接】wvp-GB28181-pro 基于GB28181-2016、部标808、部标1078标准实现的开箱即用的网络视频平台。自带管理页面,支持NAT穿透,支持海康、大华、宇视等品牌的IPC、NVR接入…...
智慧巡检-基于深度学习的指针式压力表读数识别【YOLO+OpenCv+TensorRT+ROS+Python】
智慧巡检-基于深度学习的指针式压力表读数识别【YOLOOpenCvTensorRTROSPython】 1指针式压力表读数识别系统(YOLOOpenCVTensorRTROS)一、系统整体架构 ┌──────────────────────────────────────────────…...
如何在OBS Studio中免费使用VST插件:终极音频优化完整指南
如何在OBS Studio中免费使用VST插件:终极音频优化完整指南 【免费下载链接】obs-vst Use VST plugins in OBS 项目地址: https://gitcode.com/gh_mirrors/ob/obs-vst 想要让直播或录制的声音质量瞬间达到专业级别,却不想花费高昂费用购买专业音频…...
Flutter 混合栈开发完全指南:原理、架构与双向跳转实战
在企业级移动端迭代中,几乎没人会把成熟的原生 App 全部重写为 Flutter。绝大多数场景都是 原有原生工程 部分 Flutter 新页面 的混合开发模式。而混合开发中最棘手、最核心的问题不是视图嵌入,也不是通道通信,而是 页面栈混乱:原…...
STM32 HAL库驱动DS18B20避坑指南:单总线时序不准?试试用定时器精准延时
STM32 HAL库驱动DS18B20避坑指南:单总线时序不准?试试用定时器精准延时 在嵌入式开发中,温度传感器DS18B20因其单总线接口和数字输出特性广受欢迎。然而,许多开发者在使用STM32 HAL库驱动DS18B20时,常遇到温度读取失败…...
城市交通网络信号的无模型自适应控制方法【附模型】
✨ 长期致力于城市交通网络信号控制、数据驱动控制、无模型自适应控制、无模型自适应预测控制、无模型自适应迭代学习控制、宏观基本图研究工作,擅长数据搜集与处理、建模仿真、程序编写、仿真设计。 ✅ 专业定制毕设、代码 ✅ 如需沟通交流,点击《获取方…...
清华大学打造实时交互视频生成新方案:让AI“边想边说“不再卡顿
这项由清华大学与人民大学联合开展的研究,于2026年5月以预印本形式发布,论文编号为arXiv:2605.15141,有兴趣深入了解的读者可通过该编号查询完整论文。研究团队来自清华大学和生数科技(ShengShu),与人民大学…...
2026年最新亲测3款生成会议纪要免费工具推荐,10分钟出稿非常好用!
兄弟们,我来了。作为一个天天泡在会议室、钉钉和飞书里来回切换的职场老兵,我太懂“开会一时爽,整理火葬场”的痛苦了。这几年,各种AI录音转文字、语音转写工具层出不穷,但真正能打、能免费白嫖、还不乱收费的…...
工业自动化设备电流检测解决方案——工业控制系统为什么越来越重视隔离电流检测
在工业自动化设备中,电流检测已经成为控制系统的重要组成部分。无论是PLC控制柜、伺服驱动器、工业电源、机器人控制系统还是变频器系统,控制器都需要实时获取负载电流信息,用于过流保护、闭环控制、功率计算以及设备状态监测。但很多工程师在…...
C++函数对象与仿函数
C函数对象与仿函数函数对象是重载了函数调用运算符operator()的类对象,也称为仿函数。它们可以像函数一样被调用,但比普通函数更灵活,可以保存状态和配置。函数对象的基本实现通过重载operator()实现。#include #include #includeclass Multi…...
