Android渲染-AHardwareBuffer

本文主要从应用的角度介绍android的native层AHardwareBuffer创建纹理以及保存渲染数据。

HardwareBuffer

要介绍native层的AHardwareBuffer,就需要先从Java层的HardwareBuffer说起。Android官方对于HardwareBuffer介绍如下:

HardwareBuffer wraps a native AHardwareBuffer object, which is a low-level object representing a memory buffer accessible by various hardware units. HardwareBuffer allows sharing buffers across different application processes. In particular, HardwareBuffers may be mappable to memory accessibly to various hardware systems, such as the GPU, a sensor or context hub, or other auxiliary processing units. For more information, see the NDK documentation for AHardwareBuffer.

HardwareBuffer 官方介绍为一种底层的内存 buffer 对象,可在不同进程间共享,可映射到不同硬件系统,如 GPU、传感器等,从构造函数可以看出,其可以指定 format 和 usage,用来让底层选择最合适的实现。

从HardwareBuffer的源码中可以了解到,HardwareBuffer只是 GraphicBuffer 的一个包装。在Android早期版本(API<=25), Java层并没有提供底层的GraphicBuffer API,通常使用底层由GraphicBuffer实现的Surface。因此本质上是 Android 系统开放了更底层的 API,我们才可以有更高效的实现。接下来看具体如何基于HardwareBuffer跨进程传输纹理。

通过 AHardwareBuffer_toHardwareBuffer 函数,可以将native层的AHardwareBuffer 对象转为 Java HardwareBuffer 对象,其本身实现了 Parcelable 接口,可以直接通过 AIDL 传递到另一个进程,其中具体的实现就是 Android 系统 GraphicBuffer 跨进程的方案,底层通过 fd 实现,B进程获取对应的HardwareBuffer后,可以通过AHardwareBuffer_fromHardwareBuffer继续转换为native层的AHardwareBuffer。 

AHardwareBuffer

接下来主要介绍使用AHardwareBuffer创建纹理以及通过AHardwareBuffer读取纹理图像的流程

AHardwareBuffer创建纹理

创建纹理的流程较为简单,创建AHardwareBuffer_Desc句柄,结构体赋值,本文以创建NV21的OES纹理为例,代码如下:

FUN_BEGIN_TIME("RenderContext::CreateOESTexture")if(textureID == 0){AHardwareBuffer_Desc h_buffer_desc = {0};h_buffer_desc.stride = frameData->i32Width;h_buffer_desc.height = frameData->i32Height;h_buffer_desc.width = frameData->i32Width;h_buffer_desc.layers = 1;h_buffer_desc.format = 0x11;h_buffer_desc.usage = AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN|AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;int ret = AHardwareBuffer_allocate(&h_buffer_desc, &inputHWBuffer);EGLint attr[] = {EGL_NONE};EGLDisplay edp;edp = (EGLDisplay)eglGetCurrentDisplay();inputEGLImage) = eglCreateImageKHR(edp, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, eglGetNativeClientBufferANDROID(inputHWBuffer), attr);glGenTextures(1, &textureID);glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureID);glTexParameteri(GL_TEXTURE_EXTERNAL_OES , GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_EXTERNAL_OES , GL_TEXTURE_MAG_FILTER, GL_LINEAR);glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES , (GLeglImageOES)inputEGLImage);GLUtils::CheckGLError("eglCreateImageKHR");}AHardwareBuffer_Planes planes_info = {0};int ret = AHardwareBuffer_lockPlanes(inputHWBuffer,AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK,-1,nullptr,&planes_info);if (ret != 0) {LOGI("Failed to AHardwareBuffer_lockPlanes");}else{memcpy(planes_info.planes[0].data,frameData->ppu8Plane[0],frameData->i32Width * frameData->i32Height*3/2);ret = AHardwareBuffer_unlock(inputHWBuffer, nullptr);if (ret != 0) {LOGI("Failed to AHardwareBuffer_unlock");}}glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureID);
FUN_END_TIME("RenderContext::CreateOESTexture")

AHardwareBuffer读取纹理图像数据

读取纹理图像数据的方式和创建纹理的方式类似,通过上述创建纹理的方式,我们实现了AHardwareBuffer 和 EGLImageKHR的绑定,因此,我们可以通过反向思维,将纹理读取出来,代码如下:

FUN_BEGIN_TIME("RenderContext::ReadOESTexture")unsigned char *ptrReader = nullptr;ret = AHardwareBuffer_lock(inputHWBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, -1,     nullptr, (void **) &ptrReader); memcpy(dstBuffer, ptrReader, imgWidth * imgHeight * 3 / 2);ret = AHardwareBuffer_unlock(inputHWBuffer, nullptr);
FUN_END_TIME("RenderContext::ReadOESTexture")

至此,我们可以将dstBuffer通过字节,或者其他形式,保存为图像数据。

总结

针对Android侧,我们需要理清GraphicBuffer、AHardwareBuffer、ANativeWindowBuffer之间的关系。从联系上,GraphicBuffer 继承了ANativeWindowBuffer,所以可以直接通过static_cast<>类型转换成ANativeWindowBuffer,不过由于是多继承,所以转完有一个地址偏移(static_cast 自动完成)。而AHardwareBuffer只是一个抽象的概念,没有具体类型,与GraphicBuffer 没有任何继承关系,也没有具体的类型,是个空结构体,类似于void 类型。从源码可以看到,aosp封装的那些AHardwareBuffer_xxx接口,本质上底层都是通过AHardwareBuffer_to_GraphicBuffer,转成GraphicBuffer,依旧用GraphicBuffer的形式做的后续处理。

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

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

相关文章

Java预科知识

以下内容是根据狂神的Java说、chatgpt和csdn相关博客&#xff0c;结合自己的理解完成的。 Java了解 基于Java 开发了巨多的平台&#xff0c;系统&#xff0c;工具 构建工具&#xff1a; Ant, Maven, Jekins应用服务器&#xff1a;Tomcat, Jetty, Jboss, Websphere, weblogic…

dell r720远程网络安装ubuntu20.04(无U盘)

登陆后界面&#xff0c;在主界面上&#xff0c;我们就可以看到各个硬件组件的状态。在快速启动任务栏中&#xff0c;可以对系统电源进行操作&#xff0c;如开机、关机等。安装操作系统&#xff0c;在虚拟控制台预览处点击>启动 按照浏览器出现的提示确定安装控件等&#x…

软件设计师——数据结构(一)

&#x1f4d1;前言 本文主要是【数据结构】——软件设计师——数据结构的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304…

running小程序重要技术流程文档

一、项目文件说明&#xff1a; &#xff08;注&#xff1a;getMyMoney无用已删除&#xff09; 二、重要文件介绍 1.reinfo.js&#xff1a;位于utils文件下&#xff0c;该文件封装有统一的请求URL&#xff0c;和请求API同意封装供页面调用&#xff1b;调用时候需要在页面上先…

unittest与pytest的区别

Unittest vs Pytest 主要从用例编写规则、用例的前置和后置、参数化、断言、用例执行、失败重运行和报告这几个方面比较unittest和pytest的区别: 用例编写规则 用例前置与后置条件 断言 测试报告 失败重跑机制 参数化 用例分类执行 如果不好看&#xff0c;可以看下面表格&…

算能 MilkV Duo开发板实战——opencv-mobile (迷你版opencv库)的移植和应用

前言 OpenCV是一种开源的计算机视觉和机器学习软件库&#xff0c;旨在提供一组通用的计算机视觉工具。它用于图像处理、目标识别、人脸识别、机器学习等领域&#xff0c;广泛应用于计算机视觉任务。 OpenCV-Mobile是OpenCV库的轻量版本&#xff0c;专为移动平台&#xff08;A…

[MySQL] SQL优化之性能分析

&#x1f308;键盘敲烂&#xff0c;年薪30万&#x1f308; 目录 一、索引优化 1、索引是什么&#xff1a; 2、索引的数据结构&#xff1a; 3、索引种类&#xff1a; 4、sql分析&#xff08;回表查询&#xff09; 二、定位慢查询语句 1、慢查询日志 2、profile详情 3、…

洛谷P3807 Lucas定理

传送门&#xff1a; P3807 【模板】卢卡斯定理/Lucas 定理 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P3807题干&#xff1a; 给定整数n,m,p 的值&#xff0c;求出C&#xff08;nm&#xff0c;n&#xff09;​mod p 的值。 输入数据保证…

案例027:基于微信小程序的校园二手平台的设计与实现

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

SAP UI5 walkthrough step3 Controls

在上一步&#xff0c;我们是直接用index.html 中的body 里面的DIVision去输出 hello world&#xff0c; 在这个章节&#xff0c;我们将用SAP UI5 的标准控件 sap/m/Text 首先&#xff0c;我们去修改 webapp/index.html <!DOCTYPE html> <html> <head><…

Pytorch深度强化学习1-6:详解时序差分强化学习(SARSA、Q-Learning算法)

目录 0 专栏介绍1 时序差分强化学习2 策略评估原理3 策略改进原理3.1 SARSA算法3.2 Q-Learning算法 0 专栏介绍 本专栏重点介绍强化学习技术的数学原理&#xff0c;并且采用Pytorch框架对常见的强化学习算法、案例进行实现&#xff0c;帮助读者理解并快速上手开发。同时&#…

【论文极速读】LVM,视觉大模型的GPT时刻?

【论文极速读】LVM&#xff0c;视觉大模型的GPT时刻&#xff1f; FesianXu 20231210 at Baidu Search Team 前言 这一周&#xff0c;LVM在arxiv上刚挂出不久&#xff0c;就被众多自媒体宣传为『视觉大模型的GPT时刻』&#xff0c;笔者抱着强烈的好奇心&#xff0c;在繁忙工作之…

class073 背包dp-01背包、有依赖的背包【算法】

class073 背包dp-01背包、有依赖的背包【算法】 算法讲解073【必备】背包dp-01背包、有依赖的背包 code1 P1048 [NOIP2005 普及组] 采药 // 01背包(模版) // 给定一个正数t&#xff0c;表示背包的容量 // 有m个货物&#xff0c;每个货物可以选择一次 // 每个货物有自己的体积…

ChatGPT 应用开发(一)ChatGPT OpenAI API 免代理调用方式(通过 Cloudflare 的 AI Gateway)

前言 开发 ChatGPT 应用&#xff0c;我觉得最前置的点就是能使用 ChatGPT API 接口。首先我自己要能成功访问&#xff0c;这没问题&#xff0c;会魔法就可以本地调用。 那用户如何调用到我的应用 API 呢&#xff0c;我的理解是通过用户能访问到的中转服务器向 OpenAI 发起访问…

带阻滤波器:原理、应用及性能分析?|深圳比创达电子EMC

在现代电子技术和通信领域中&#xff0c;滤波器是一种常见的电路元件&#xff0c;用于处理信号&#xff0c;去除不需要的频率成分或者增强感兴趣的频率成分。本文将重点探讨带阻滤波器&#xff0c;它是一种特殊类型的滤波器&#xff0c;具有在特定频率范围内抑制信号的功能。我…

JVM Optimization Learning(五)

目录 一、JVM Optimization 1、G1 1、G1内存模型 2、基础概念 3、G1特点&#xff1a; 4、CMS日志分析 5、G1日志分析 2、GC参数 2.1、GC常用参数 2.2、Parallel常用参数 2.3、CMS常用参数 2.4、G1常用参数 一、JVM Optimization 1、G1 G1官网说明&#xff1a;Gar…

【微软技术栈】发布自己造的轮子 -- 创建Nuget包(分布操作)

目录 1、您的项目 2、创建 .nuspec 文件 3、一张图片胜过一千个拉取请求 4、包括自述文件 MD 文件 5、构建软件包 6、将包部署到 Nuget.Org 7、手动上传软件包 8、自动化和脚本化部署 9、我们如何构建和部署 ErrLog.IO Nuget 包 10、Nuget统计数据 11、最后的思考 创建 Nuget 包…

生产上线需要注意的安全漏洞

一、关闭swagger 1、关闭swagger v3 # 需同时设置auto-startupfalse&#xff0c;否则/v3/api-docs等接口仍能继续访问 springfox:documentation:enabled: falseauto-startup: falseswagger-ui:enabled: false 2、关闭swagger v2 # 只要不是true就不启用 swagger:enable: fa…

YOLOv8/YOLOv7/YOLOv5/YOLOv4/Faster-rcnn系列算法改进【NO.83】将主干特征提取网络Backbone改为RevCol

前言 作为当前先进的深度学习目标检测算法YOLOv8,已经集合了大量的trick,但是还是有提高和改进的空间,针对具体应用场景下的检测难点,可以不同的改进方法。此后的系列文章,将重点对YOLOv8的如何改进进行详细的介绍,目的是为了给那些搞科研的同学需要创新点或者搞工程项目…

Vue3: 给表格多个字段添加排序功能

问题 在Vue3项目中&#xff0c;使用element-plus的表格组件绘制表格后&#xff0c;需要令表格的多个字段可以进行选择排序&#xff08;选择升序或者降序&#xff09;但是排序功能好像有时候会出错&#xff0c;需要排序的字段多了之后&#xff0c;排序功能有时候会不起作用 解…