当前位置: 首页 > news >正文

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,不允许这种情况。

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(&params);params.nPortIndex = portIndex;params.enable = enable;err = OMX_SetParameter(mHandle, index, &params);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(&params);params.nPortIndex = portIndex;params.enable = enable;err = OMX_SetParameter(mHandle, index, &params);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(&params);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, &params);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, &params);}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 的创建过程&#xff0c;以及 IOmx 服务和 OMXNodeInstance、OMX组件之间的联系。接下来我们将一起了解 ACodec 是如何通过 OMXNodeInstance 这个中间层进行端口定义设置&#xff0c;以及端口Buffer分配的。 OMXNodeInstance 的代码还是比较长…...

生物系统学中的进化树构建和分析R工具包V.PhyloMaker2的介绍和详细使用

V.PhyloMaker2是一个R语言的工具包&#xff0c;专门用于构建和分析生物系统学中的进化树&#xff08;也称为系统发育树或phylogenetic tree&#xff09;。以下是对V.PhyloMaker2的一些基本介绍和使用说明&#xff1a; 论文介绍&#xff1a;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如何实现了链表的基本操作&#xff08;增删改查&#xff09;2.4 LinkedList的遍历方式 三、 …...

计算机网络复习-OSI TCP/IP 物理层

我膨胀了&#xff0c;挂我啊~ 作者简介&#xff1a; 每年都吐槽吉师网安奇怪的课程安排、全校正经学网络安全不超20人情景以及割韭菜企业合作的FW&#xff0c;今年是第一年。。 TCP/IP模型 先做两道题&#xff1a; TCP/IP协议模型由高层到低层分为哪几层&#xff1a; 这题…...

虚拟机服务器中了lockbit2.0/3.0勒索病毒怎么处理,数据恢复应对步骤

网络技术的不断发展也为网络威胁带来了安全隐患&#xff0c;近期&#xff0c;对于许多大型企业来说&#xff0c;许多企业的虚拟机服务器系统遭到了lockbit2.0/3.0勒索病毒攻击&#xff0c;导致企业所有计算机系统瘫痪&#xff0c;无法正常工作&#xff0c;严重影响了企业的正常…...

【MATLAB】 RGB和YCbCr互转

前言 在视频、图像处理领域经常会遇到不同色域图像的转换&#xff0c;比如RGB、YUV、YCbCr色域间的转换&#xff0c;这里提供一组转换公式&#xff0c;供大家参考。 色彩模型 RGB RGB色彩模型是一种用于表示数字图像的颜色空间&#xff0c;其中"RGB"代表红色&…...

【线性代数】决定张成空间的最少向量线性无关吗?

答1&#xff1a; 是的&#xff0c;张成空间的最少向量是线性无关的。 在数学中&#xff0c;张成空间&#xff08;span space&#xff09;是一个向量空间&#xff0c;它由一组向量通过线性组合&#xff08;即每个向量乘以一个标量&#xff09;生成。如果这组向量是线性无关的&…...

暴力破解(Pikachu)

基于表单的暴力破解 先随便输入一下&#xff0c;然后抓包&#xff0c;进行字典爆破 验证码绕过(on server) server服务端要输入正确的验证码后进行爆破 之后的操作没什么不一样 验证码绕过(on client) 这个也需要输入验证码&#xff0c;但是后面进行字典爆破的时候&#xf…...

如何使用CMake查看opencv封装好的函数

当我们有时想查看opencv自带的函数的源代码&#xff0c;比如函数cvCreateImage, 此时我们选中cvCreateImage, 点击鼠标右键->转到定义&#xff0c;我们会很惊讶的发现为什么只看到了cvCreateImage的一个简单声明&#xff0c;而没有源代码呢&#xff1f;这是因为openCV将很多…...

微盛·企微管家:用户运营API集成,电商无代码解决方案

连接电商平台的新纪元&#xff1a;微盛企微管家 随着电子商务的蓬勃发展&#xff0c;电商平台的高效运营已经成为企业成功的关键。在这个新纪元里&#xff0c;微盛企微管家以其创新的无代码开发连接方案&#xff0c;成为企业之间连接电商平台的强大工具。它允许企业轻松集成电…...

Hive 部署

一、介绍 Apache Hive是一个分布式、容错的数据仓库系统&#xff0c;支持大规模的分析。Hive Metastore&#xff08;HMS&#xff09;提供了一个中央元数据存储库&#xff0c;可以轻松地进行分析&#xff0c;以做出明智的数据驱动决策&#xff0c;因此它是许多数据湖架构的关键组…...

CopyOnWriteArrayList源码阅读

1、构造方法 无参构造函数 //创建一个空数组&#xff0c;赋值给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 共享文件夹的优点 优点 协作和团队合作&#xff1a;共享文件夹使多个用户能够在同一文件夹中协作和编辑文件。这促进了团…...

STM32独立看门狗

时钟频率 40KHZ 看门狗简介 STM32F10xxx 内置两个看门狗&#xff0c;提供了更高的安全性、时间的精确性和使用的灵活性。两个看 门狗设备 ( 独立看门狗和窗口看门狗 ) 可用来检测和解决由软件错误引起的故障&#xff1b;当计数器达到给 定的超时值时&#xff0c;触发一个中…...

财务数据智能化:用AI工具高效制作财务分析PPT报告

Step1: 文章内容提取 WPS AI 直接打开文件&#xff0c;在AI对话框里输入下面指令&#xff1a; 假设你是财务总监&#xff0c;公司考虑与茅台进行业务合作、投资或收购&#xff0c;请整合下面茅台2021年和2022年的财务报告信息。整理有关茅台财务状况和潜在投资回报的信息&…...

vue3中使用three.js记录

记录一下three.js配合vitevue3的使用。 安装three.js 使用npm安装&#xff1a; npm install --save three开始使用 1.定义一个div <template><div ref"threeContainer" class"w-full h-full"></div> </template>可以给这个di…...

MySQL——表的内外连接

目录 一.内连接 二.外连接 1.左外连接 2.右外连接 一.内连接 表的连接分为内连和外连 内连接实际上就是利用where子句对两种表形成的笛卡儿积进行筛选&#xff0c;我们前面学习的查询都是内连接&#xff0c;也是在开发过程中使用的最多的连接查询。 语法&#xff1a; s…...

基于IPP-FFT的线性调频Z(Chirp-Z,CZT)的C++类库封装并导出为dll(固定接口支持更新)

上一篇分析了三种不同导出C++类方法的优缺点,同时也讲了如何基于IPP库将FFT函数封装为C++类库,并导出为支持更新的dll库供他人调用。 在此基础上,结合前面的CZT的原理及代码实现,可以很容易将CZT变换也封装为C++类库并导出为dll,关于CZT的原理和实现,如有问题请参考: …...

【C语言】指针

基本概念 在C语言中&#xff0c;指针是一种非常重要的数据类型&#xff0c;它用于存储变量的内存地址。指针提供了对内存中数据的直接访问&#xff0c;使得在C语言中可以进行灵活的内存操作和数据传递。以下是关于C语言指针的一些基本概念&#xff1a; 1. 指针的声明&#xff…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

使用SSE解决获取状态不一致问题

使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件&#xff0c;这个上传文件是整体功能的一部分&#xff0c;文件在上传的过程中…...

jdbc查询mysql数据库时,出现id顺序错误的情况

我在repository中的查询语句如下所示&#xff0c;即传入一个List<intager>的数据&#xff0c;返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致&#xff0c;会导致返回的id是从小到大排列的&#xff0c;但我不希望这样。 Query("SELECT NEW com…...

aardio 自动识别验证码输入

技术尝试 上周在发学习日志时有网友提议“在网页上识别验证码”&#xff0c;于是尝试整合图像识别与网页自动化技术&#xff0c;完成了这套模拟登录流程。核心思路是&#xff1a;截图验证码→OCR识别→自动填充表单→提交并验证结果。 代码在这里 import soImage; import we…...

基于stm32F10x 系列微控制器的智能电子琴(附完整项目源码、详细接线及讲解视频)

注&#xff1a;文章末尾网盘链接中自取成品使用演示视频、项目源码、项目文档 所用硬件&#xff1a;STM32F103C8T6、无源蜂鸣器、44矩阵键盘、flash存储模块、OLED显示屏、RGB三色灯、面包板、杜邦线、usb转ttl串口 stm32f103c8t6 面包板 …...

【版本控制】GitHub Desktop 入门教程与开源协作全流程解析

目录 0 引言1 GitHub Desktop 入门教程1.1 安装与基础配置1.2 核心功能使用指南仓库管理日常开发流程分支管理 2 GitHub 开源协作流程详解2.1 Fork & Pull Request 模型2.2 完整协作流程步骤步骤 1: Fork&#xff08;创建个人副本&#xff09;步骤 2: Clone&#xff08;克隆…...

简约商务通用宣传年终总结12套PPT模版分享

IOS风格企业宣传PPT模版&#xff0c;年终工作总结PPT模版&#xff0c;简约精致扁平化商务通用动画PPT模版&#xff0c;素雅商务PPT模版 简约商务通用宣传年终总结12套PPT模版分享:商务通用年终总结类PPT模版https://pan.quark.cn/s/ece1e252d7df...

Python异步编程:深入理解协程的原理与实践指南

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 持续学习&#xff0c;不断…...

[C++错误经验]case语句跳过变量初始化

标题&#xff1a;[C错误经验]case语句跳过变量初始化 水墨不写bug 文章目录 一、错误信息复现二、错误分析三、解决方法 一、错误信息复现 write.cc:80:14: error: jump to case label80 | case 2:| ^ write.cc:76:20: note: crosses initialization…...

SDU棋界精灵——硬件程序ESP32实现opus编码

一、 ​​音频处理框架​ 该项目基于Espressif的音频处理框架构建,核心组件包括 ESP-ADF 和 ESP-SR,以下是完整的音频处理框架实现细节: 1.核心组件 (1) 音频前端处理 (AFE - Audio Front-End) ​​main/components/audio_pipeline/afe_processor.c​​功能​​: 声学回声…...