Android Camera HAL架构从原理到实战项目 - 第3节
3.1 HAL3 设计理念:从 HAL1 到 HAL3 的演进
Android Camera HAL3 架构的核心设计理念是 “流水线化” 与 “请求-响应” 模型。与 HAL1 的同步、阻塞式操作不同,HAL3 允许应用层同时提交多个捕获请求(Capture Request),硬件抽象层可以并行处理这些请求,并按照完成顺序返回结果。这种设计大幅提升了多摄像头协同、高帧率连拍和复杂后处理场景的性能。
设计目标: 将 Camera 子系统从“黑盒”变为“可编程管线”,让应用层能够精确控制每一帧的传感器、ISP、后处理参数。
3.1.1 HAL1 vs HAL3 核心差异
| 对比维度 | HAL1 | HAL3 |
|---|---|---|
| 操作模型 | 同步、阻塞式 | 异步、流水线式 |
| 帧控制粒度 | 粗粒度(预览/拍照/录像模式切换) | 逐帧精细控制(曝光、增益、对焦、AE/AWB 锁定等) |
| 多摄像头支持 | 逻辑摄像头映射复杂 | 原生支持物理摄像头组与逻辑摄像头 |
| 输出流数量 | 通常 1~2 路 | 支持多路并行输出(YUV、RAW、HEIC、Depth 等) |
| Buffer 管理 | HAL 内部管理 | Gralloc + 框架统一管理,支持 Buffer 复用 |
关键理解: HAL3 将 Camera 从“设备驱动”提升为“图像处理引擎”,每一帧都是一个独立的“任务”,包含完整的 3A 参数、输出流规格和后处理配置。
3.2 Camera3Module:模块入口与设备管理
camera3_module_t 是 HAL3 的顶层入口结构体,由 HAL 库导出。框架通过 open() 方法获取 camera3_device_t 实例,进而操作具体的 Camera 设备。
// hardware/libhardware/include/hardware/camera3.h
typedef struct camera3_module {
hw_module_t common;
int (*get_number_of_cameras)(void);
int (*get_camera_info)(int camera_id, struct camera_info *info);
int (*set_callbacks)(const camera3_callback_ops_t *callbacks);
void (*get_vendor_tag_ops)(vendor_tag_ops_t *ops);
int (*open_legacy)(const struct hw_module_t* module, const char* id,
uint32_t halVersion, struct hw_device_t** device);
// ... 其他扩展接口
} camera3_module_t;
3.2.1 Module 核心职责
- 设备枚举: 通过
get_number_of_cameras()和get_camera_info()向框架报告可用 Camera 设备及其静态能力(如分辨率、AE 补偿范围、支持的数据格式等)。 - 回调注册:
set_callbacks()注册框架回调,用于 HAL 上报错误、Buffer 释放等异步事件。 - 设备打开:
open()方法创建camera3_device_t,每个 Camera ID 对应一个设备实例。
注意: 在 HAL3 中,
open() 调用会触发 camera3_device_t->ops->initialize(),此时 HAL 应完成所有硬件资源预分配,但 不启动 数据流。
3.3 Camera3Device:设备接口与操作契约
camera3_device_t 代表一个具体的 Camera 硬件设备,其操作函数集 camera3_device_ops_t 定义了 HAL 与框架之间的核心交互契约。
typedef struct camera3_device {
hw_device_t common;
camera3_device_ops_t *ops;
void *priv; // HAL 私有数据指针
} camera3_device_t;
typedef struct camera3_device_ops {
int (*initialize)(const struct camera3_device *,
const camera3_callback_ops_t *callback_ops);
int (*configure_streams)(const struct camera3_device *,
camera3_stream_configuration_t *config);
int (*construct_default_request_settings)(
const struct camera3_device *, int type);
int (*process_capture_request)(const struct camera3_device *,
camera3_capture_request_t *request);
void (*dump)(const struct camera3_device *, int fd);
int (*flush)(const struct camera3_device *);
// ... 其他操作
} camera3_device_ops_t;
3.3.1 关键操作流程
- initialize():初始化设备,注册框架回调。此时 HAL 应准备好所有内部资源。
- configure_streams():配置输出流集合。框架根据应用层需求(预览、拍照、录像)组合多个
camera3_stream_t,HAL 需确认是否支持并分配 Buffer 池。 - construct_default_request_settings():为指定模板(如预览、拍照、录像)生成默认的捕获请求设置。
- process_capture_request():提交一个捕获请求。这是 HAL3 最核心的异步调用,HAL 必须尽快返回,并在完成后通过回调通知框架。
- flush():清空所有待处理的请求,用于快速关闭或异常恢复。
核心原则:
process_capture_request() 必须是非阻塞的。HAL 内部应使用工作线程池处理请求,并通过 camera3_callback_ops_t 中的 process_capture_result() 返回结果。
3.4 Pipeline:请求处理流水线
Pipeline 是 HAL3 内部对“从传感器曝光到输出 Buffer 完成”这一完整处理路径的抽象。每个 Camera 设备可以包含多个 Pipeline,每个 Pipeline 对应一个物理摄像头或一个逻辑处理阶段。
3.4.1 Pipeline 关键特性
- 深度流水线: 支持多个请求同时处于不同处理阶段,提高吞吐量。
- 逐帧参数: 每个请求可以携带独立的 3A 参数、裁剪区域、输出格式等。
- Buffer 管理: 输入/输出 Buffer 由框架通过
camera3_stream_buffer_t传递,HAL 负责填充或消费。
实战提示: 在实现 HAL3 时,Pipeline 深度通常设置为 3~6 帧。过浅会导致 CPU 等待,过深会增加延迟。建议根据 Sensor 帧率和 ISP 处理时间动态调整。
3.5 Stream:输出流与配置
camera3_stream_t 是 HAL3 中描述输出 Buffer 规格的核心结构体。一个 Camera 设备可以同时配置多个 Stream,每个 Stream 对应一路独立的输出(如预览 YUV、拍照 JPEG、RAW 数据等)。
typedef struct camera3_stream {
int stream_type; // CAMERA3_STREAM_OUTPUT / INPUT / BIDIRECTIONAL
uint32_t width;
uint32_t height;
int format; // HAL_PIXEL_FORMAT_*
uint32_t usage; // GRALLOC_USAGE_*
uint32_t max_buffers; // HAL 建议的最大 Buffer 数
void *priv; // HAL 私有数据
android_dataspace_t data_space;
int rotation;
// ... 其他字段
} camera3_stream_t;
3.5.1 Stream 配置流程
- 框架收集: 应用层通过
CameraDevice.createCaptureSession()指定输出 Surface 集合。 - Stream 组合: 框架将 Surface 转换为
camera3_stream_t数组,调用configure_streams()。 - HAL 确认: HAL 检查是否支持该组合,并设置
max_buffers、usage等字段。 - Buffer 分配: 框架根据 HAL 返回的配置分配 Gralloc Buffer,并注册到 HAL。
3.5.2 常见 Stream 类型对比
| Stream 类型 | 典型格式 | 用途 | Buffer 方向 |
|---|---|---|---|
| OUTPUT | YUV420_888 / NV12 / JPEG | 预览、拍照、录像 | HAL 写入 → 框架消费 |
| INPUT | YUV420_888 / RAW10 | 重处理(Reprocess) | 框架写入 → HAL 消费 |
| BIDIRECTIONAL | YUV420_888 | ZSL(零快门延迟) | 双向 |
Stream 配置约束: 一旦
configure_streams() 成功返回,Stream 集合在 flush() 或 close() 之前不可更改。如果需要动态调整输出规格,必须先停止当前 Session,重新配置。
3.6 请求-响应模型详解
HAL3 的核心数据流模型是 Capture Request → Capture Result。每个请求包含以下关键信息:
typedef struct camera3_capture_request {
uint32_t frame_number; // 帧序号,单调递增
camera3_stream_buffer_t *input_buffers; // 输入 Buffer(重处理时使用)
uint32_t num_input_buffers;
camera3_stream_buffer_t *output_buffers; // 输出 Buffer 列表
uint32_t num_output_buffers;
const camera_metadata_t *settings; // 逐帧 3A 参数
int32_t *physical_camera_settings; // 多摄像头时各物理 Camera 参数
// ...
} camera3_capture_request_t;
3.6.1 请求生命周期
- 提交: 框架调用
process_capture_request(),HAL 必须立即返回(非阻塞)。 - 处理: HAL 内部将请求加入 Pipeline,Sensor 曝光、ISP 处理、后处理依次执行。
- 结果回调: 处理完成后,HAL 通过
process_capture_result()返回结果元数据(3A 状态、时间戳等)和填充好的 Buffer。 - Buffer 释放: 框架消费完 Buffer 后,通过
buffer_release()回调通知 HAL 可以复用。
关键约束: 结果回调的顺序 不一定 与请求提交顺序一致。HAL 可以乱序返回结果,但必须保证每个
frame_number 唯一且最终都会返回。框架通过 frame_number 关联请求与结果。
3.7 本章小结
- HAL3 设计理念: 异步流水线、逐帧精细控制、多流并行输出。
- Camera3Module: 模块入口,负责设备枚举、能力查询和设备打开。
- Camera3Device: 设备接口,定义
configure_streams()、process_capture_request()等核心操作。 - Pipeline: 请求处理流水线,支持多请求并行处理,深度通常为 3~6 帧。
- Stream: 输出流抽象,支持 OUTPUT、INPUT、BIDIRECTIONAL 三种类型,配置后不可动态修改。
- 请求-响应模型: 非阻塞提交、异步回调、乱序返回,通过
frame_number保证一致性。