2、Camera HAL 基础回顾:HAL3 架构、Pipeline、Stream、Buffer、Request 核心概念
在深入多路 Stream 并行捕获配置之前,必须牢固掌握 Camera HAL3 的核心抽象。HAL3 接口(Android 7.0+ 强制)将 Camera 子系统从传统的“黑盒”模式重构为 Pipeline + Request 的显式控制模型。本节将逐一拆解 HAL3 架构、Pipeline、Stream、Buffer 和 Request 这五个基石。
2.1 HAL3 整体架构
HAL3 位于 Android Camera Framework(CameraService / CameraDevice)与底层 Camera 硬件驱动(Kernel / Sensor / ISP)之间。其核心设计哲学是 “一次配置,多次请求”:通过 configure_streams() 建立固定的数据通路(Pipeline),然后通过重复提交 capture() / flush() 请求来驱动数据流动。
2.2 Pipeline:数据通路抽象
Pipeline 是 HAL3 中 从 Sensor 输出到最终输出 Buffer 的完整处理链路。每个 Pipeline 对应一个固定的硬件处理路径(例如:主摄 → ISP → 缩放模块 → JPEG 编码器)。
- 物理 Pipeline: 直接映射到硬件 ISP 通道,每个物理 Camera 设备通常包含 1~3 条物理 Pipeline。
- 逻辑 Pipeline: 在多摄(Multi-Camera)场景下,Framework 可以将多个物理 Pipeline 组合为一个逻辑 Pipeline,实现无缝变焦或 Fusion。
- Pipeline 特征: 分辨率限制、帧率限制、格式支持、处理延迟(Pipeline Latency)。
2.3 Stream:输出数据通道
Stream 是 HAL3 中 描述输出数据格式、分辨率、用途的通道定义。每个 Stream 对应一个 camera3_stream_t 结构体,在 configure_streams() 时一次性配置。
| Stream 字段 | 类型 | 说明 | 多路并行关键约束 |
|---|---|---|---|
stream_type |
int | CAMERA3_STREAM_OUTPUT / INPUT / BIDIRECTIONAL | 多路捕获通常全部为 OUTPUT |
width / height |
uint32_t | 输出图像分辨率 | 受 Pipeline 最大分辨率限制 |
format |
int | HAL_PIXEL_FORMAT_YCbCr_420_888 / BLOB / RAW16 / IMPLEMENTATION_DEFINED | 不同格式可能占用不同 ISP 资源 |
usage |
uint32_t | GRALLOC_USAGE_SW_* / GRALLOC_USAGE_HW_* | GPU/Video/Display 等不同消费者 |
max_buffers |
uint32_t | HAL 建议的 Buffer 队列深度 | 影响并行请求的 Buffer 分配策略 |
data_space |
android_dataspace_t | 色彩空间(HAL_DATASPACE_STANDARD_BT709 等) | 多路输出需保持一致性 |
2.4 Buffer:数据载体
Buffer 是 Stream 中实际承载图像数据的 内存块,通过 Gralloc 分配。HAL3 使用 Dequeue / Enqueue 模型管理 Buffer 生命周期。
- Buffer 分配时机: 在
configure_streams()时,HAL 通过camera3_stream_t.max_buffers告知 Framework 需要预分配的 Buffer 数量。 - Buffer 流转路径: Framework 从 Stream 的 BufferQueue 中 Dequeue 空闲 Buffer → 填充到 Request 中 → HAL 填充数据 → Framework 将 Buffer 送给消费者(SurfaceView / MediaCodec / ImageReader)。
- Buffer 复用: 在多路并行场景下,同一个物理 Buffer 可以被多个 Stream 共享吗?不可以。每个 Stream 拥有独立的 Buffer 队列,即使分辨率相同,也必须分配独立的 Buffer 实例。
2.5 Request:捕获命令单元
Request 是 HAL3 中 一次捕获操作的完整描述,对应 camera3_capture_request_t 结构体。它是驱动整个 Pipeline 工作的“触发器”。
| Request 字段 | 说明 | 多路并行中的角色 |
|---|---|---|
frame_number |
帧序号,单调递增 | 用于追踪多路 Stream 中同一时刻的帧同步 |
settings |
AE/AWB/AF 等 3A 参数(camera_metadata_t) |
多路 Stream 共享同一组 settings(或通过 request_template 微调) |
input_buffer |
输入 Buffer(仅 reprocess 场景) | 多路并行通常为 NULL |
output_buffers |
输出 Buffer 数组(camera3_stream_buffer_t) |
核心字段:一个 Request 可以包含多个 output_buffers,每个指向不同的 Stream |
num_output_buffers |
输出 Buffer 数量 | 决定本次 Request 需要填充多少个 Stream |
2.6 核心概念关系总结
下表总结了五个核心概念在 HAL3 多路并行捕获中的角色与关系:
| 概念 | 数据结构 | 配置时机 | 多路并行中的角色 |
|---|---|---|---|
| HAL3 架构 | camera3_device_ops_t |
设备打开时 | 定义 Framework 与 HAL 的交互契约 |
| Pipeline | 硬件抽象路径 | 芯片设计时固定 | 决定 ISP 带宽上限和格式支持 |
| Stream | camera3_stream_t |
configure_streams() |
定义每个输出通道的格式/分辨率/用途 |
| Buffer | camera3_stream_buffer_t |
Request 提交时 | 承载实际图像数据,每个 Stream 独立队列 |
| Request | camera3_capture_request_t |
每次捕获提交 | 将多个 Stream 的 Buffer 打包为一个原子捕获单元 |
① 一个 Request 最多可以携带多少个 output_buffers?(答案:取决于 HAL 实现,但 Framework 层无硬性上限,通常受 ISP 物理通道数限制)
② 如果两个 Stream 的分辨率相同,能否共用同一个 Buffer?(答案:不能,每个 Stream 必须拥有独立的 Buffer 实例)
③
configure_streams() 调用后,Stream 的哪些属性可以动态改变?(答案:只有 usage 和 max_buffers 可以在某些 HAL 实现中动态调整,width/height/format 必须重新配置)