2. 核心数据结构:camera3_device_t、camera3_callback_ops_t、camera3_stream_t 结构体详解
在 Camera HAL3 框架中,camera3_device_t、camera3_callback_ops_t 和 camera3_stream_t 是构成 HAL 层与 Framework 通信的三大核心数据结构。它们分别定义了 HAL 设备接口、回调操作集和流配置描述。理解这三个结构体是掌握 CaptureRequest 处理流程的基础。
学习提示: 这三个结构体均定义在
hardware/libhardware/include/hardware/camera3.h 中。建议读者在阅读本节时,对照源码中的结构体定义进行学习。
2.1 camera3_device_t:HAL 设备抽象
camera3_device_t 是 HAL3 设备在 Framework 侧的抽象表示。它继承自 hw_device_t,并扩展了 HAL3 特有的操作函数指针。Framework 通过该结构体调用 HAL 层的初始化、配置流、提交请求等核心接口。
关键点:
camera3_device_t 是 Framework 与 HAL 交互的“门把手”,所有针对特定 Camera 设备的操作都通过其 ops 字段中的函数指针完成。
typedef struct camera3_device {
hw_device_t common; // 继承自 hw_device_t,包含版本号、模块句柄等
camera3_device_ops_t *ops; // 操作函数指针集,HAL 必须实现
void *priv; // HAL 私有数据指针,Framework 不直接使用
} camera3_device_t;
下表列出了 camera3_device_ops_t 中最重要的几个函数指针及其职责:
| 函数指针 | 职责描述 | 调用时机 |
|---|---|---|
initialize() |
初始化 HAL 设备,传入回调接口 camera3_callback_ops_t |
Camera 打开后、配置流之前 |
configure_streams() |
配置输出/输入流数组,HAL 据此分配硬件资源 | 初始化后、首次提交请求前,或重新配置时 |
process_capture_request() |
提交一个 CaptureRequest 给 HAL 处理 | 每次应用层请求拍照或预览帧时 |
flush() |
清空所有正在处理的请求,尽快返回 | 关闭 Camera 或发生错误时 |
dump() |
输出 HAL 内部状态用于调试 | Framework 请求 dump 信息时 |
2.2 camera3_callback_ops_t:异步事件通知通道
camera3_callback_ops_t 是 Framework 提供给 HAL 的回调函数集合。HAL 在处理请求的过程中,通过该结构体中的函数指针将结果帧、错误信息、缓冲区状态等异步事件通知给 Framework。该结构体在 initialize() 调用时由 Framework 传入。
typedef struct camera3_callback_ops {
void (*process_capture_result)(const struct camera3_callback_ops *,
const camera3_capture_result_t *result);
void (*notify)(const struct camera3_callback_ops *,
const camera3_notify_msg_t *msg);
} camera3_callback_ops_t;
两个回调函数的职责对比如下:
| 回调函数 | 触发时机 | 传递数据 | 线程安全要求 |
|---|---|---|---|
process_capture_result() |
HAL 完成一个 CaptureRequest 的部分或全部输出时 | camera3_capture_result_t,包含 metadata、输出缓冲区、部分结果标识 |
必须可重入,可在任意线程调用 |
notify() |
发生错误、快门事件或请求被丢弃时 | camera3_notify_msg_t,包含错误码、帧编号、时间戳 |
必须可重入,可在任意线程调用 |
常见陷阱: HAL 实现必须在调用
process_capture_result() 之前确保输出缓冲区的内容已经写入完毕。Framework 收到回调后可能立即读取缓冲区数据,因此 HAL 不能持有对缓冲区的引用。
2.3 camera3_stream_t:流配置描述
camera3_stream_t 描述了一个 Camera 数据流的配置信息,包括图像格式、分辨率、使用方向、最大缓冲区数等。在 configure_streams() 调用中,Framework 传入一个 camera3_stream_t 数组,HAL 需要根据这些配置分配硬件资源并设置 usage、max_buffers 和 priv 字段。
typedef struct camera3_stream {
int stream_type; // CAMERA3_STREAM_OUTPUT / INPUT / BIDIRECTIONAL
uint32_t width; // 图像宽度(像素)
uint32_t height; // 图像高度(像素)
int format; // 像素格式,如 HAL_PIXEL_FORMAT_YCbCr_420_888
uint32_t usage; // 缓冲区使用标志,由 HAL 填充
uint32_t max_buffers; // HAL 请求的最大缓冲区数
void *priv; // HAL 私有数据
android_dataspace_t data_space; // 数据空间(颜色空间等)
int rotation; // 输出旋转角度
int reserved[6]; // 保留字段
} camera3_stream_t;
下表列出了 stream_type 的三种取值及其典型用途:
| 流类型 | 枚举值 | 典型用途 | 数据方向 |
|---|---|---|---|
CAMERA3_STREAM_OUTPUT |
0 | 预览、拍照、视频录制输出 | HAL → Framework |
CAMERA3_STREAM_INPUT |
1 | YUV 重处理输入(如美颜、滤镜) | Framework → HAL |
CAMERA3_STREAM_BIDIRECTIONAL |
2 | ZSL 输入输出复用流 | 双向 |
实现要点: HAL 在
configure_streams() 中必须检查 format 和 usage 的兼容性。例如,如果 format 为 HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,HAL 可以选择最高效的内部格式,但必须保证与 usage 标志兼容。
2.4 三者协作关系总结
在 CaptureRequest 的完整生命周期中,三个结构体按照以下顺序协作:
- 设备打开: Framework 通过 HAL 模块获取
camera3_device_t实例。 - 初始化: Framework 调用
ops->initialize(),传入camera3_callback_ops_t回调接口。 - 流配置: Framework 调用
ops->configure_streams(),传入camera3_stream_t数组,HAL 填充usage、max_buffers等字段。 - 请求处理: Framework 调用
ops->process_capture_request(),HAL 处理完成后通过camera3_callback_ops_t返回结果。 - 错误处理: 发生异常时,HAL 通过
notify()回调上报错误信息。
最佳实践: 在实现 HAL 时,建议将
camera3_device_t 的 priv 字段指向一个包含所有设备状态(包括流列表、回调指针、内部线程句柄)的上下文结构体。这样可以避免使用全局变量,提高代码的可维护性和线程安全性。