2. 核心数据结构:camera3_device_t、camera3_callback_ops_t、camera3_stream_t 结构体详解
Camera HAL3 接口的核心在于三个关键数据结构:camera3_device_t、camera3_callback_ops_t 和 camera3_stream_t。它们分别代表了 HAL 设备实例、回调通信通道和图像流配置。理解这三个结构体是编写 HAL3 适配代码的基础。
2.1 camera3_device_t:HAL 设备实例
camera3_device_t 是 Camera HAL3 中代表单个摄像头设备的结构体。它继承自 Android 硬件抽象层的基础设备结构 hw_device_t,并扩展了摄像头特有的操作接口。该结构体是 Framework 与 HAL 交互的入口点。
| 字段 | 类型 | 说明 |
|---|---|---|
common |
hw_device_t |
基础硬件设备结构,包含版本号、模块句柄、关闭函数等通用字段。 |
ops |
camera3_device_ops_t* |
指向操作函数表的指针,包含 initialize、configure_streams、process_capture_request 等核心方法。 |
priv |
void* |
私有数据指针,HAL 实现方用于关联自定义的设备上下文(如传感器驱动句柄、状态机等)。 |
关键点:
ops 字段是 HAL3 接口的核心,所有捕获请求、流配置、元数据回调都通过该指针指向的函数表完成。HAL 实现必须在 open() 函数中正确填充 ops 和 priv。
以下是一个典型的 camera3_device_t 初始化代码片段:
// HAL 实现中的 open() 函数片段
int my_camera_device_open(const struct hw_module_t* module,
const char* id,
struct hw_device_t** device) {
my_camera_device_t* my_dev = (my_camera_device_t*)calloc(1, sizeof(*my_dev));
if (!my_dev) return -ENOMEM;
// 填充 common 字段
my_dev->device.common.tag = HARDWARE_DEVICE_TAG;
my_dev->device.common.version = CAMERA_DEVICE_API_VERSION_3_5;
my_dev->device.common.module = (hw_module_t*)module;
my_dev->device.common.close = my_camera_device_close;
// 填充 ops 函数表
my_dev->device.ops = &my_camera_device_ops;
// 填充私有数据
my_dev->device.priv = my_dev->priv_data;
*device = &my_dev->device.common;
return 0;
}
2.2 camera3_callback_ops_t:异步回调通道
camera3_callback_ops_t 是 Framework 向 HAL 注册的一组回调函数指针。HAL 通过这组回调将捕获结果、错误信息、快门事件等异步通知给 Framework。该结构体在 initialize() 调用时由 Framework 传入。
| 回调函数 | 触发时机 | 说明 |
|---|---|---|
process_capture_result |
捕获完成时 | 返回捕获结果元数据(camera3_capture_result_t)和输出缓冲区。 |
notify |
事件发生时 | 发送快门事件、错误事件等异步通知(camera3_notify_msg_t)。 |
flush |
Framework 请求刷新时 | 通知 HAL 尽快完成或取消所有待处理的请求(Android 8.0+ 新增)。 |
实现提示: HAL 必须保存
camera3_callback_ops_t 指针,并在捕获线程中安全地调用 process_capture_result 和 notify。回调调用必须是线程安全的,且不能阻塞 Framework 的调用线程。
回调注册流程示例:
// HAL 的 initialize() 实现
int my_device_initialize(const struct camera3_device *device,
const camera3_callback_ops_t *callback_ops) {
my_camera_device_t* my_dev = (my_camera_device_t*)device->priv;
// 保存回调指针
my_dev->callback_ops = callback_ops;
// 初始化传感器、ISP 等硬件
// ...
return 0;
}
// 在捕获完成时调用回调
void my_capture_completed(my_camera_device_t* my_dev,
camera3_capture_result_t* result) {
my_dev->callback_ops->process_capture_result(
my_dev->callback_ops, result);
}
2.3 camera3_stream_t:图像流配置
camera3_stream_t 描述了一个图像流的属性,包括分辨率、格式、使用场景等。该结构体在 configure_streams() 调用中由 Framework 传入,HAL 需要根据这些配置初始化 ISP 管线。
| 字段 | 类型 | 说明 |
|---|---|---|
stream_type |
int |
流类型:CAMERA3_STREAM_OUTPUT(输出)、CAMERA3_STREAM_INPUT(输入)、CAMERA3_STREAM_BIDIRECTIONAL(双向)。 |
width / height |
uint32_t |
图像分辨率(像素)。 |
format |
int |
像素格式,如 HAL_PIXEL_FORMAT_YCbCr_420_888、HAL_PIXEL_FORMAT_BLOB(JPEG)、HAL_PIXEL_FORMAT_RAW16。 |
usage |
uint32_t |
使用标志位,如 GRALLOC_USAGE_SW_READ_OFTEN、GRALLOC_USAGE_HW_CAMERA_WRITE。 |
max_buffers |
uint32_t |
HAL 请求的最大缓冲区数量(由 HAL 在 configure_streams() 中设置)。 |
priv |
void* |
HAL 私有数据指针,可用于关联每个流的上下文(如 DMA 通道、缓冲区队列)。 |
data_space |
android_dataspace_t |
色彩空间,如 HAL_DATASPACE_V0_JFIF(JPEG)、HAL_DATASPACE_STANDARD_BT709。 |
rotation |
int |
输出旋转角度:CAMERA3_STREAM_ROTATION_0、90、180、270。 |
常见陷阱:
max_buffers 必须在 configure_streams() 返回前由 HAL 设置。如果设置过小,可能导致预览卡顿或拍照失败;设置过大则浪费内存。通常预览流设置为 3~4,拍照流设置为 1~2。
流配置处理示例:
// HAL 的 configure_streams() 实现片段
int my_configure_streams(const struct camera3_device *device,
camera3_stream_configuration_t *stream_list) {
my_camera_device_t* my_dev = (my_camera_device_t*)device->priv;
for (size_t i = 0; i < stream_list->num_streams; i++) {
camera3_stream_t* stream = stream_list->streams[i];
// 根据流类型和格式配置硬件
if (stream->stream_type == CAMERA3_STREAM_OUTPUT) {
if (stream->format == HAL_PIXEL_FORMAT_BLOB) {
// JPEG 拍照流:设置最大缓冲区为 1
stream->max_buffers = 1;
// 配置 JPEG 编码器
} else if (stream->format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
// 预览流:设置最大缓冲区为 4
stream->max_buffers = 4;
// 配置预览管线
}
}
// 为每个流分配私有上下文
stream->priv = my_alloc_stream_context(stream);
}
return 0;
}
2.4 三个结构体的协作关系
在 Camera HAL3 的运行时环境中,这三个结构体通过以下方式协同工作:
- 初始化阶段: Framework 通过
camera3_device_t.ops->initialize()将camera3_callback_ops_t注册到 HAL。 - 流配置阶段: Framework 通过
configure_streams()传入camera3_stream_t数组,HAL 根据这些配置初始化硬件管线。 - 捕获阶段: Framework 发送
camera3_capture_request_t,其中包含指向camera3_stream_t的缓冲区句柄。 - 结果返回阶段: HAL 通过
camera3_callback_ops_t.process_capture_result()返回填充好的缓冲区及元数据。
最佳实践: 在 HAL 实现中,建议将
camera3_device_t 的 priv 指针指向一个包含设备状态、回调指针、流列表和硬件句柄的自定义结构体。这样可以避免全局变量,提高代码的可维护性和线程安全性。