Android 系统中AHardwareBuffer、ANativeWindowBuffer和GraphicBuffer的关系

server/2024/9/23 3:44:41/

Android Camera软件系统中,每路Stream的Buffer都是DMA-BUF,这种Buffer通常对外暴露的结构是ANativeWindowBuffer或GraphicBuffer(跨进程传递时用的native_handle_t),本文介绍Android系统中AHardwareBuffer、ANativeWindowBuffer和GraphicBuffer的关系。ANativeWindowBuffer、AHardwareBuffer都是GraphicBuffer通过类型转换而来,ANativeWindowBuffer对native_handle_t进行了封装。

ANativeWindowBuffer

ANativeWindowBuffer定义在nativebase.h头文件中。

frameworks/native/libs/nativebase/include/nativebase/nativebase.h

定义如下:

typedef struct ANativeWindowBuffer
{
#ifdef __cplusplusANativeWindowBuffer() {common.magic = ANDROID_NATIVE_BUFFER_MAGIC;common.version = sizeof(ANativeWindowBuffer);memset(common.reserved, 0, sizeof(common.reserved));}// Implement the methods that sp<ANativeWindowBuffer> expects so that it// can be used to automatically refcount ANativeWindowBuffer's.void incStrong(const void* /*id*/) const {common.incRef(const_cast<android_native_base_t*>(&common));}void decStrong(const void* /*id*/) const {common.decRef(const_cast<android_native_base_t*>(&common));}
#endifstruct android_native_base_t common;int width;int height;int stride;int format;int usage_deprecated;uintptr_t layerCount;void* reserved[1];const native_handle_t* handle;uint64_t usage;// we needed extra space for storing the 64-bits usage flags// the number of slots to use from reserved_proc depends on the// architecture.void* reserved_proc[8 - (sizeof(uint64_t) / sizeof(void*))];
} ANativeWindowBuffer_t;typedef struct ANativeWindowBuffer ANativeWindowBuffer;

可以看到它是一个结构体,重要的成员有:

  • handle
  • width
  • height
  • stride
  • format
  • usage

ANativeWindowBuffer描述的是一块DMA Buffer,handle中包含了Buffer的FD,其他成员是该Buffer的一些描述/补充。

GraphicBuffer

GraphicBuffer的头文件分为
– frameworks/native/libs/ui/include_vndk/ui/GraphicBuffer.h
– frameworks/native/libs/ui/include/ui/GraphicBuffer.h

GraphicBuffer继承自ANativeWindowBuffer。

我们可以在Vendor/System分区使用GraphicBuffer,用到的库是libui.so(支持VNDK)。

AHardwareBuffer

AHardwareBuffer定义在

frameworks/native/libs/nativewindow/include/android/hardware_buffer.h

定义如下:

/*** Opaque handle for a native hardware buffer.*/
typedef struct AHardwareBuffer AHardwareBuffer;

所以,AHardwareBuffer是一个抽象的概念,没有具体类型(类似void类型),主要用于在同一进程的不同模块间传递ANativeWindowBuffer。

GraphicBuffer 与 ANativeWindowBuffer相互转换

GraphicBuffer提供了接口来做转换,使用的static_cast

GraphicBuffer转成ANativeWindowBuffer:

ANativeWindowBuffer* GraphicBuffer::getNativeBuffer() const
{return static_cast<ANativeWindowBuffer*>(const_cast<GraphicBuffer*>(this));
}

ANativeWindowBuffer转换成GraphicBuffer:

sp<GraphicBuffer> GraphicBuffer::from(ANativeWindowBuffer* anwb) {return static_cast<GraphicBuffer *>(anwb);
}

AHardwareBuffer 与 GraphicBuffer 相互转换

GraphicBuffer提供了接口来做转换,使用的reinterpret_cast

AHardwareBuffer 转换成GraphicBuffer:

GraphicBuffer* GraphicBuffer::fromAHardwareBuffer(AHardwareBuffer* buffer) {return reinterpret_cast<GraphicBuffer*>(buffer);
}

GraphicBuffer转换成AHardwareBuffer:

AHardwareBuffer const* GraphicBuffer::toAHardwareBuffer() const {return reinterpret_cast<AHardwareBuffer const*>(this);
}

AHardwareBuffer 与 ANativeWindowBuffer相互转换

他们两不能直接转换,必须借助GraphicBuffer来作为中间桥梁。

AHardwareBuffer转换成ANativeWindowBuffer:

frameworks/native/libs/nativewindow/AHardwareBuffer.cpp定义了AHardwareBuffer_to_ANativeWindowBuffer方法完成该转换(注:无法在Vendor分区使用)

ANativeWindowBuffer* AHardwareBuffer_to_ANativeWindowBuffer(AHardwareBuffer* buffer) {return AHardwareBuffer_to_GraphicBuffer(buffer)->getNativeBuffer();
}

先将AHardwareBuffer转换成GraphicBuffer,然后再调用GraphicBuffer的getNativeBuffer。

ANativeWindowBuffer转换成AHardwareBuffer:

先将ANativeWindowBuffer转换成GraphicBuffer,再调用toAHardwareBuffer获取到HardwareBuffer。

sp<GraphicBuffer> GraphicBuffer::from(ANativeWindowBuffer* anwb) {return static_cast<GraphicBuffer *>(anwb);
}AHardwareBuffer* GraphicBuffer::toAHardwareBuffer() {return reinterpret_cast<AHardwareBuffer*>(this);
}

如何创建ANativeWindowBuffer

为了让ANativeWindowBuffer有智能指针的作用,需要定义一个类继承自ANativeWindowBuffer和android::RefBase(如果不想要智能指针的作用则不用做这一步)。

举例:

class NativeBuffer : public ANativeWindowBuffer, public android::RefBase
{
public:void incStrong(const void* id) const { RefBase::incStrong(id); }void decStrong(const void* id) const { RefBase::decStrong(id); }NativeBuffer(INT32 widthIn, INT32 heightIn, INT32 strideIn, INT32 formatIn,INT32 usageIn, native_handle_t *handleIn) :ANativeWindowBuffer(), RefBase(){width           = widthIn;height          = heightIn;stride          = strideIn;format          = formatIn;usage           = usageIn;handle          = handleIn;common.incRef   = incRef;common.decRef   = decRef;}private:static void incRef(android_native_base_t* base){NativeBuffer *self = static_cast<NativeBuffer*>(reinterpret_cast<ANativeWindowBuffer*>(base));self->incStrong(self);}static void decRef(android_native_base_t* base){NativeBuffer *self = static_cast<NativeBuffer*>(reinterpret_cast<ANativeWindowBuffer*>(base));self->decStrong(self);}
};

这里面主要实现incRef和decRef,会尝试static_cast检查能否正常进行转换,然后调用RefBase相应的接口。

使用时,直接new NativeBuffer

new NativeBuffer(width, height, stride, m_formatInput, m_usage, static_cast<native_handle_t*>(pImage->pNativeHandle));

reinterpret_cast与static_cast的作用和区别

reinterpret_cast用于执行低级别的类型转换,可以将一个指针或引用转换为另一种不同类型的指针或引用。它允许将任何指针类型转换为任何其他指针类型,即使它们之间没有任何关系。这种转换是非常危险的,潜在地导致未定义行为,因此应该谨慎使用。reinterpret_cast通常用于底层编程,例如将指针转换为整数类型或将数据强制转换为特定的内存布局。

static_cast是一种较为安全的类型转换操作符,它主要用于相关类型之间的转换,例如整数之间的转换、父类指针/引用到子类指针/引用的转换等。static_cast会在编译时进行类型检查,并检查是否存在可行的转换路径。如果存在转换,则进行转换,否则会产生编译错误。相对于reinterpret_cast,static_cast提供了更多的类型安全性,并且在一定程度上减少了潜在的错误。

总结一下:

  • reinterpret_cast执行低级别的类型转换,允许将任何指针类型转换为任何其他指针类型,但是风险较高,容易导致未定义行为。
  • static_cast用于相关类型之间的转换,提供了较为安全的类型转换,并在编译时进行类型检查,如果存在可行的转换路径,则进行转换,否则产生编译错误。

http://www.ppmy.cn/server/45900.html

相关文章

JavaScript基础知识1(引入方式、注释、输入输出、变量、数组)

JavaScript基础知识1&#xff08;引入方式、注释、输入输出、变量、数组&#xff09; javascript 引入方式内部方式外部形式 注释和结束符单行注释多行注释 结束符 输入和输出输出输入 alert(你好JS);document.write(js我来了);console.log(看看对不对);prompt(输入您的姓名&am…

学 Go 具体能干什么?

学习 Go (Golang) 后&#xff0c;你可以从事许多不同的工作和项目&#xff0c;Go 语言以其高性能、并发处理和简洁的语法而闻名&#xff0c;特别适合以下几个领域&#xff1a; 1. 后端开发 Go 在后端开发中非常流行&#xff0c;特别适合构建高性能的 Web 服务和 API。 Web 框…

5.二叉树详解(附习题)

1.二叉树链式结构的实现 1.1 前置说明 在学习二叉树的基本操作前&#xff0c;需先要创建一棵二叉树&#xff0c;然后才能学习其相关的基本操作。本文准备讲述一些二叉树的基础知识&#xff0c;此处手动快速创建一棵简单的二叉树&#xff0c;来快速进入二叉 树 操作学习&#x…

【Oracle】修改已经存在的序列的当前值

前情提要 在oracle中一般使用序列来实现ID自增。但是oracle中序列维护的没有mysql那么好。只是单存的递增。 比如新建了一个序列&#xff0c;从1开始&#xff0c;每次递增1。此时我向数据库里插入一条id10的数据。那么在序列查询到10的时候&#xff0c;插入就会报错。 所以比较…

3225mm晶振SG3225CAN专用于蓝牙模块应用

在无线通信技术迅猛发展的今天&#xff0c;蓝牙技术因其低功耗、高传输速率和广泛的应用范围&#xff0c;成为物联网和智能设备的重要组成部分。晶振在蓝牙模块中无处不在&#xff0c;大部分的智能手机&#xff0c;打开设置工具里面就会有一个是蓝牙功能&#xff0c;蓝牙技术引…

实验名称:字符串练习

欢迎收看你的月亮我的心&#xff01;大家好&#xff01;我是肖老师,我又回来了&#xff01; 一、实验目的&#xff1a; 统计不同字符&#xff08;字母、数字、空格、其他字符&#xff09;的个数编写程序&#xff0c;检查字符串”Life is short.I use python”中是否包含字符串…

c++指针的*

1.*运算符 *运算符被称为间接值&#xff08;indirect value&#xff09;或者解除引用&#xff08;dereferencing&#xff09;运算符 将其应用于指针可以得到该地址处存储的值 由于 * 也有乘法的意思&#xff0c;c通过上下文来确定是乘法还是解除引用 2.如何声明和初始化指针 …

一些图形界面的工具可以帮助你模拟点击和进行其他浏览器自动化操作

1. Selenium IDE Selenium IDE 是一个用于记录、编辑和调试测试的集成开发环境。它有一个图形界面,允许你通过点击和录制来创建测试用例。它支持Chrome和Firefox浏览器。 安装和使用步骤: 在Chrome或Firefox的扩展商店中搜索“Selenium IDE”并安装。打开Selenium IDE扩展。…