4. Camera HAL 核心数据结构详解
Camera HAL 的架构围绕一组核心数据结构展开,它们定义了 HAL 模块的加载方式、设备生命周期、以及数据流的传输协议。理解这些结构体是进行 HAL 移植、调试和性能优化的基础。本章将深入剖析 camera_module_t、camera_device_t、camera3_device_t 和 camera3_stream_t 等关键结构体。
4.1 模块入口:camera_module_t
camera_module_t 是 HAL 层与 Android 框架交互的起点。它定义在 hardware/libhardware/include/hardware/camera_common.h 中,是 HAL 模块的标准接口。
| 字段 | 类型 | 说明 |
|---|---|---|
| common | hw_module_t | 标准 HAL 模块头,包含模块 ID、版本、作者等信息。 |
| get_number_of_cameras | int (*)(void) | 返回系统中可用的摄像头数量。 |
| get_camera_info | int (*)(int camera_id, struct camera_info *info) | 获取指定摄像头的静态信息,如朝向、设备类型(前置/后置/外接)。 |
| set_callbacks | int (*)(const camera_module_callbacks_t *callbacks) | 注册框架回调,用于通知 HAL 模块热插拔事件或设备状态变化。 |
| get_vendor_tag_ops | void (*)(vendor_tag_ops_t* ops) | (可选)提供厂商自定义 metadata tag 的操作接口。 |
| open_legacy | int (*)(const struct hw_module_t* module, const char* id, uint32_t halVersion, struct hw_device_t** device) | (可选)打开指定 HAL 版本的设备,用于兼容旧版 Camera HAL。 |
| set_torch_mode | int (*)(const char* camera_id, bool enabled) | (可选)独立控制闪光灯 torch 模式,无需打开 camera device。 |
| init | int (*)(void) | (可选)模块级初始化,在 hw_get_module 之后调用。 |
get_number_of_cameras 和 get_camera_info 是必须实现的基础接口。如果设备支持热插拔 USB 摄像头,务必正确实现 set_callbacks 以通知框架设备状态变化。
4.2 设备抽象:camera_device_t 与 camera3_device_t
这两个结构体分别对应 Camera HAL v1 和 v3 的设备抽象。v1 是旧版接口,v3 是当前主流接口,支持更复杂的 pipeline 和 metadata 控制。
4.2.1 camera_device_t (HAL v1)
定义在 hardware/libhardware/include/hardware/camera.h,是 v1 接口的设备句柄。
typedef struct camera_device {
hw_device_t common; // 标准设备头
camera_device_ops_t *ops; // 操作函数指针表
void *priv; // HAL 私有数据指针
} camera_device_t;
其中 camera_device_ops_t 包含了 start_preview、stop_preview、take_picture 等传统操作函数。
4.2.2 camera3_device_t (HAL v3)
定义在 hardware/libhardware/include/hardware/camera3.h,是 v3 接口的核心设备结构体。
typedef struct camera3_device {
hw_device_t common; // 标准设备头
camera3_device_ops_t *ops; // v3 操作函数指针表
void *priv; // HAL 私有数据指针
} camera3_device_t;
camera3_device_ops_t 是 v3 接口的灵魂,包含以下关键函数:
- initialize:初始化设备,传入框架回调
camera3_callback_ops_t。 - configure_streams:配置数据流,是 pipeline 建立的核心入口。
- register_stream_buffers:注册 stream 的 buffer 句柄(Android N 后已废弃)。
- process_capture_request:提交一次 capture 请求,包含 metadata 和 buffer 信息。
- flush:异步刷新所有正在处理的请求。
- dump:导出设备调试信息。
4.3 数据流核心:camera3_stream_t
camera3_stream_t 定义了单个数据流的属性,是 configure_streams 中传递的基本单元。它描述了框架期望 HAL 输出的图像格式、分辨率、使用场景等。
| 字段 | 类型 | 说明 |
|---|---|---|
| stream_type | int | 流类型:CAMERA3_STREAM_OUTPUT (输出)、CAMERA3_STREAM_INPUT (输入)、CAMERA3_STREAM_BIDIRECTIONAL (双向)。 |
| width | uint32_t | 图像宽度(像素)。 |
| height | uint32_t | 图像高度(像素)。 |
| format | int | 像素格式,如 HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED、HAL_PIXEL_FORMAT_YCbCr_420_888、HAL_PIXEL_FORMAT_BLOB。 |
| usage | uint32_t | Gralloc buffer 使用标志,如 GRALLOC_USAGE_SW_READ_OFTEN、GRALLOC_USAGE_HW_TEXTURE。 |
| max_buffers | uint32_t | HAL 请求的最大 buffer 数量,由 HAL 在 configure_streams 中设置。 |
| priv | void * | HAL 私有数据指针,用于关联 stream 对应的硬件 pipeline 上下文。 |
| data_space | android_dataspace_t | 色彩空间,如 HAL_DATASPACE_STANDARD_BT709。 |
| rotation | int | 输出旋转角度:0、90、180、270。 |
| physical_camera_id | const char * | (Android 9+)物理摄像头 ID,用于多摄场景。 |
configure_streams 中,HAL 必须根据硬件能力调整 max_buffers 和 usage 字段。如果 HAL 无法支持框架请求的格式或分辨率组合,必须返回 -EINVAL 并重新协商。忽略此规则会导致预览黑屏或拍照失败。
4.4 结构体关系总览
下图展示了 Camera HAL v3 中核心结构体的层次关系与数据流向:
4.5 实战:从结构体到代码实现
在 HAL 实现中,通常会将核心结构体封装到自定义的上下文对象中。以下是一个典型的 HAL v3 设备初始化片段:
// 自定义 HAL 设备上下文
typedef struct my_camera_device {
camera3_device_t base; // 必须作为第一个字段
camera3_device_ops_t ops; // 操作函数表
int camera_id;
void *sensor_handle; // 传感器驱动句柄
// ... 其他私有成员
} my_camera_device_t;
// 实现 open 函数
int my_camera_device_open(const struct hw_module_t* module,
const char* id,
struct hw_device_t** device) {
my_camera_device_t *dev = malloc(sizeof(my_camera_device_t));
memset(dev, 0, sizeof(*dev));
// 填充标准设备头
dev->base.common.tag = HARDWARE_DEVICE_TAG;
dev->base.common.version = CAMERA_DEVICE_API_VERSION_3_5;
dev->base.common.module = (hw_module_t*)module;
dev->base.common.close = my_camera_device_close;
// 绑定操作函数表
dev->ops.initialize = my_initialize;
dev->ops.configure_streams = my_configure_streams;
dev->ops.process_capture_request = my_process_capture_request;
dev->ops.flush = my_flush;
dev->ops.dump = my_dump;
dev->base.ops = &dev->ops;
dev->camera_id = atoi(id);
// ... 初始化硬件
*device = &dev->base.common;
return 0;
}
camera3_device_t 作为第一个成员,这样框架通过 hw_device_t 指针强制转换后,能正确访问到 ops 和 priv 字段。这是 HAL 层常见的“继承”实现模式。
4.6 关键结构体对比总结
| 结构体 | 所属层级 | 核心作用 | 关键函数/字段 |
|---|---|---|---|
| camera_module_t | 模块层 | HAL 入口,枚举设备 | get_number_of_cameras, get_camera_info |
| camera3_device_t | 设备层 | 设备实例,管理 pipeline | ops->configure_streams, ops->process_capture_request |
| camera3_stream_t | 数据流层 | 定义单路流的属性 | format, width, height, max_buffers |
| camera3_stream_buffer_t | Buffer 层 | 绑定 buffer 与 stream | stream, buffer, status, acquire_fence |
| camera3_capture_request_t | 请求层 | 封装一次 capture 请求 | frame_number, settings, input_buffers, output_buffers |