4. HAL3 核心数据结构详解
Android Camera HAL3 接口围绕四个核心数据结构构建了完整的相机管道:设备描述、数据流、请求提交与结果返回。理解这些结构是掌握多摄切换与 Pipeline 资源管理的基础。本章逐一拆解其字段含义、生命周期与协作关系。
学习提示:HAL3 的四个核心结构对应着 Camera 框架的“设备-流-请求-结果”四元组。在多摄场景下,每个物理 Camera 设备都拥有一套独立的
camera3_stream_t 集合,而 camera3_capture_request_t 则负责跨设备的同步触发。
4.1 camera3_device_t:HAL 设备句柄
camera3_device_t 是 Camera HAL 设备在框架层的抽象表示,每个逻辑 Camera(包括多摄中的主摄、广角、长焦)都对应一个独立的 camera3_device_t 实例。它由 open() 调用创建,由 close() 销毁。
typedef struct camera3_device {
// HAL 设备版本号,必须为 HARDWARE_DEVICE_API_VERSION(3, x)
hw_device_t common;
// 设备私有数据指针,HAL 实现方使用
void *priv;
// 操作函数集:初始化、配置流、提交请求等
camera3_device_ops_t *ops;
// 预留字段
void *reserved[2];
} camera3_device_t;
关键字段说明:
- common:继承自
hw_device_t,包含 tag、版本号、模块句柄、close 函数指针。框架通过common.close()关闭设备。 - priv:HAL 实现方存放设备上下文(如 Pipeline 管理器指针、传感器驱动句柄)的私有区域。
- ops:指向
camera3_device_ops_t结构体,包含initialize()、configure_streams()、process_capture_request()、flush()等核心接口。
4.2 camera3_stream_t:数据流描述
camera3_stream_t 描述一条从 Camera 传感器到内存缓冲区的数据通道。在多摄场景中,每个物理 Camera 可以同时拥有多个流(预览流、拍照流、视频流),而逻辑 Camera 则通过 camera3_stream_configuration_t 聚合所有物理流的配置。
typedef struct camera3_stream {
// 流类型:CAMERA3_STREAM_OUTPUT / INPUT / BIDIRECTIONAL
int stream_type;
// 图像宽度、高度(像素)
uint32_t width;
uint32_t height;
// 图像格式:HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED / YCbCr_420_888 / BLOB 等
int format;
// 使用标记:GRALLOC_USAGE_HW_TEXTURE / GRALLOC_USAGE_HW_CAMERA_WRITE 等
uint32_t usage;
// 最大缓冲数(HAL 可修改)
uint32_t max_buffers;
// 私有指针:HAL 用于关联 Pipeline 内部状态
void *priv;
// 数据空间(颜色空间、动态范围等)
android_dataspace_t data_space;
// 旋转角度
int rotation;
// 物理 Camera ID(多摄时标识该流属于哪个物理 Camera)
const char *physical_camera_id;
// 预留字段
void *reserved[6];
} camera3_stream_t;
| 字段 | 说明 | 多摄场景注意事项 |
|---|---|---|
stream_type |
OUTPUT(输出到内存)、INPUT(输入到 ISP)、BIDIRECTIONAL | 多摄主输出流通常为 OUTPUT;RAW 流用于第三方算法 |
format |
像素格式,常用 IMPLEMENTATION_DEFINED 让 HAL 自行选择 | 不同物理 Camera 可能支持不同格式,需在 configure_streams 时协商 |
max_buffers |
HAL 请求的缓冲深度,框架会尽量满足 | 多摄并发时总缓冲数受内存限制,需合理分配 |
physical_camera_id |
Android 10+ 引入,标识流所属的物理 Camera | 逻辑 Camera 通过此字段将流路由到对应物理 Pipeline |
常见陷阱:在多摄切换场景中,
physical_camera_id 必须在 configure_streams() 阶段正确设置。如果框架传递的流中 physical_camera_id 为 NULL,HAL 应将其视为逻辑 Camera 的主流。切换时,HAL 需要重新配置流的 physical_camera_id 映射关系,否则会导致数据路由错误。
4.3 camera3_capture_request_t:捕获请求
每次拍照、预览帧或视频帧的采集都由一个 camera3_capture_request_t 发起。它包含了帧号、目标流、控制参数以及物理 Camera 的元数据。在多摄同步场景中,一个请求可以同时包含多个物理 Camera 的设置。
typedef struct camera3_capture_request {
// 帧号,单调递增,用于追踪请求与结果的对应关系
uint32_t frame_number;
// 请求关联的 output stream 指针数组
const camera3_stream_t *const *output_buffers;
// output_buffers 数组长度
uint32_t num_output_buffers;
// 输入 stream(用于 reprocess 场景)
const camera3_stream_t *input_buffer;
// 请求元数据(settings),包含 3A 参数、AE/AWB 模式、裁剪区域等
const camera_metadata_t *settings;
// 物理 Camera settings 数组(Android 9+),用于多摄独立控制
uint32_t num_physcam_settings;
const camera_metadata_t *const *physcam_settings;
// 物理 Camera ID 数组,与 physcam_settings 一一对应
const char *const *physcam_id;
// 预留字段
void *reserved[4];
} camera3_capture_request_t;
多摄同步请求关键点:
- frame_number:全局递增,逻辑 Camera 和物理 Camera 共享同一帧号序列。HAL 必须保证每个
frame_number对应的结果最终返回。 - physcam_settings:当逻辑 Camera 包含多个物理 Camera 时,框架通过此数组传递每个物理 Camera 独立的 3A 参数。例如主摄使用中心测光,广角使用平均测光。
- output_buffers:指向
camera3_stream_buffer_t数组,每个 buffer 关联一个 stream。多摄场景下,一个请求可能包含来自不同物理 Camera 的多个 output buffer。
4.4 camera3_capture_result_t:捕获结果
HAL 通过 camera3_capture_result_t 将处理后的帧数据、元数据和状态返回给框架。每个 frame_number 对应一个最终结果,但 HAL 可以分多次返回 partial result(例如先返回 metadata,再返回 buffer)。
typedef struct camera3_capture_result {
// 对应请求的帧号
uint32_t frame_number;
// 结果元数据(最终 3A 状态、传感器时间戳、统计信息等)
const camera_metadata_t *result;
// 输出 buffer 数组(已填充数据的 buffer)
uint32_t num_output_buffers;
const camera3_stream_buffer_t *output_buffers;
// 输入 buffer(reprocess 场景)
const camera3_stream_buffer_t *input_buffer;
// partial result 序号:1 表示第一个 partial,递增到 num_partial_results
uint32_t partial_result;
// 物理 Camera 结果元数据(Android 9+)
uint32_t num_physcam_metadata;
const camera_metadata_t *const *physcam_metadata;
const char *const *physcam_ids;
// 预留字段
void *reserved[6];
} camera3_capture_result_t;
| 字段 | 作用 | 多摄场景行为 |
|---|---|---|
frame_number |
与请求的 frame_number 匹配 | 所有物理 Camera 的结果共享同一 frame_number,框架据此合并 |
partial_result |
标识 partial result 序号,0 表示最终结果 | 每个物理 Camera 可以独立返回 partial result,框架按序号合并 |
physcam_metadata |
物理 Camera 的独立元数据 | 包含每个物理 Camera 的 AE/AWB 状态、镜头位置等,框架用于 UI 显示 |
output_buffers |
填充完成的 buffer 数组 | 多摄场景下,每个物理 Camera 的 buffer 通过此数组返回,框架根据 stream 的 physical_camera_id 区分 |
性能关键点:在多摄同步模式下,HAL 必须等待所有物理 Camera 的帧处理完成后才能返回最终结果。如果某个物理 Camera 出现丢帧或延迟,会导致整个逻辑 Camera 的帧率下降。建议在 HAL 实现中为每个物理 Pipeline 设置独立的超时监控,并在超时时返回错误状态而非无限等待。
4.5 四元组协作流程总结
四个核心数据结构在 Camera HAL3 中的协作遵循以下时序:
- 设备初始化:框架调用
open()获得camera3_device_t,然后调用ops->initialize()传入回调接口。 - 流配置:框架构造
camera3_stream_t数组,通过ops->configure_streams()传递给 HAL。HAL 根据physical_camera_id分配 Pipeline 资源。 - 请求提交:框架填充
camera3_capture_request_t,设置frame_number、settings、output_buffers和physcam_settings,调用ops->process_capture_request()。 - 结果返回:HAL 通过回调函数返回
camera3_capture_result_t,包含处理后的 buffer 和元数据。框架根据frame_number匹配请求与结果。
实战建议:在多摄 HAL 实现中,建议为每个
camera3_device_t 维护一个帧号到请求上下文的映射表。当收到 process_capture_request 时,将请求拆分为多个物理 Pipeline 子请求,并记录每个子请求的完成状态。只有当所有物理子请求都完成时,才组装最终结果并回调框架。这样可以保证多摄同步的时序正确性。