Android中 BufferQueue 和 Gralloc

目录

零、本篇讨论范围

接上篇 SurfaceFlinger做Layer合成时,如何与HAL层进行交互 后:

本篇的讨论范围如下图红框中所示:这回关注的是 图片流的生产者与消费者间数据怎么传递的。

一、图片数据流的生产者与消费者

1.1 生产者

如图上面红框所示:

包含了 MediaPlayer,Camera Preview,NDK,OpenGL ES、Canvas 2D 和 mediaserver 视频解码器。

1.2 消费者

如图下面红框所示:

图像流的最常见的消费者是 SurfaceFlinger,该系统服务会消费当前可见的 Surface,并使用窗口管理器中提供的信息将它们合成到屏幕。SurfaceFlinger 是可以修改所显示部分内容的唯一服务。SurfaceFlinger 使用 OpenGL 和 Hardware Composer 来合成一组 Surface。

OpenGL ES 应用也可以消耗图像流,例如相机应用会消耗相机预览图像流。

二、生产者与消费者间数据的传递

2.1 BufferQueue

上图为 BufferQueue 通信过程。

BufferQueue 是将缓冲区池与队列相结合的数据结构,它使用 Binder IPC 在进程之间传递缓冲区。

使用方创建并拥有 BufferQueue 数据结构,并且可存在于与其生产方不同的进程中。当生产方需要缓冲区时,它会通过调用 dequeueBuffer() 从 BufferQueue 请求一个可用的缓冲区,并指定缓冲区的宽度、高度、像素格式和用法标志。(这个上一篇提到过,其实就是 FrameBuffer,Gralloc中分配显存时,也提到过)

然后,生产方填充缓冲区并通过调用 queueBuffer() 将缓冲区返回到队列。接下来,使用方通过 acquireBuffer() 获取该缓冲区并使用该缓冲区的内容。当使用方操作完成后,它会通过调用 releaseBuffer() 将该缓冲区返回到队列。同步框架可控制缓冲区在 Android 图形管道中移动的方式。

BufferQueue 的一些特性(例如可以容纳的最大缓冲区数)由生产方和使用方联合决定。但是,BufferQueue 会根据需要分配缓冲区。除非特性发生变化,否则将会保留缓冲区;例如,如果生产方请求具有不同大小的缓冲区,系统会释放旧的缓冲区,并根据需要分配新的缓冲区。

注意:BufferQueue 永远不会复制缓冲区内容,因为移动如此多的数据是非常低效的操作。相反,缓冲区始终通过句柄进行传递。

2.2 Gralloc

Gralloc 分配器 HAL(源码路径:hardware/libhardware/include/hardware/gralloc.h)根据用途标志 执行缓冲区分配。用途标志包括以下属性:(不仅仅这几种哈,上一篇也提到过)

  • 从软件 (CPU) 访问内存的频率
  • 从硬件 (GPU) 访问内存的频率
  • 是否将内存用作 OpenGL ES (GLES) 纹理
  • 视频编码器是否会使用内存

例如,如果生产者的缓冲区格式指定 RGBA_8888 像素,并且生产者指明将从软件访问缓冲区(这意味着应用将在 CPU 上触摸像素),则 Gralloc 将按照 R-G-B-A 的顺序为每个像素创建 4 个字节的缓冲区。如果情况相反,生产者指明仅从硬件访问其缓冲区且缓冲区作为 GLES 纹理,Gralloc 可以执行 GLES 驱动程序所需的任何操作(比如 BGRA 排序、非线性搅和布局和替代颜色格式等)。允许硬件使用其首选格式可以提高性能。

某些值在特定平台上无法组合。例如,视频编码器标志可能需要 YUV 像素,因此将无法添加软件访问权限并指定RGBA_8888。

Gralloc 返回的句柄可以通过 Binder 在进程之间进行传递。我猜测,这个句柄就是FrameBuffer的内存首地址。

与上一节最后呼应。

相关推荐
阿巴斯甜6 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker7 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq95278 小时前
Andorid Google 登录接入文档
android
黄林晴9 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab21 小时前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿1 天前
Android MediaPlayer 笔记
android
Jony_1 天前
Android 启动优化方案
android
阿巴斯甜1 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇1 天前
AOSP15 Input专题InputReader源码分析
android
_小马快跑_1 天前
Kotlin | 协程调度器选择:何时用CoroutineScope配置,何时用launch指定?
android