4. HAL核心数据结构详解
在QCOM平台Camera HAL层开发中,理解核心数据结构是构建稳定、高性能相机系统的基石。本章将深入剖析五个关键数据结构:camera_module_t、camera_device_t、camera3_device_t、camera3_stream_t 和 camera3_capture_request_t,涵盖它们的定义、职责、成员变量以及在HAL层中的典型使用模式。
4.1 数据结构全景图
下图展示了HAL层核心数据结构之间的层次关系与数据流向。从模块加载到设备打开,再到流配置与捕获请求提交,每个结构体都承担着明确的职责。
4.2 camera_module_t:模块入口
camera_module_t 是HAL层暴露给Framework的第一个结构体,定义在 hardware/libhardware/include/hardware/camera_common.h 中。它代表整个相机模块,负责枚举物理相机设备并打开它们。
4.2.1 核心成员
| 成员 | 类型 | 说明 |
|---|---|---|
| common | hw_device_t | 硬件模块通用结构,包含 tag、version、module_api_version 等 |
| get_number_of_cameras | int (*)(void) | 返回系统中可用的相机设备数量 |
| get_camera_info | int (*)(int id, struct camera_info *info) | 获取指定ID相机的静态信息(朝向、支持的分辨率等) |
| set_callbacks | int (*)(const camera_module_callbacks_t *callbacks) | 注册Framework回调,用于热插拔通知等 |
| open_legacy | int (*)(const struct hw_module_t*, const char*, uint32_t, struct hw_device_t**) | 打开HAL1兼容设备(可选) |
4.2.2 QCOM平台实现要点
- 模块初始化:在
camera_module_t的common中设置module_api_version = CAMERA_MODULE_API_VERSION_3_0,表明支持HAL3。 - 设备枚举:
get_number_of_cameras返回物理相机数 + 逻辑相机数(如双摄虚化)。 - 热插拔:通过
set_callbacks注册的回调,在USB相机插入/拔出时通知Framework。
camera_module_t 通常由 mm-camera-impl 库实现,模块加载时通过 HAL_MODULE_INFO_SYM 符号导出。
4.3 camera_device_t 与 camera3_device_t:设备抽象
这两个结构体分别对应HAL1和HAL3的设备抽象。在QCOM平台中,HAL3是主流,camera_device_t 仅用于兼容旧版应用。
4.3.1 camera_device_t(HAL1)
定义在 hardware/libhardware/include/hardware/camera.h,核心是 camera_device_ops_t 函数指针表:
typedef struct camera_device {
hw_device_t common;
camera_device_ops_t *ops; // 操作函数表
void *priv; // 私有数据,指向HAL内部实现
} camera_device_t;
camera_device_ops_t 包含 set_preview_window、start_preview、take_picture 等HAL1接口。
4.3.2 camera3_device_t(HAL3)
定义在 hardware/libhardware/include/hardware/camera3.h,是HAL3的核心设备结构体:
typedef struct camera3_device {
hw_device_t common;
camera3_device_ops_t *ops; // HAL3操作函数表
void *priv; // 私有数据
} camera3_device_t;
camera3_device_ops_t 包含以下关键回调:
| 回调函数 | 说明 |
|---|---|
| initialize | 初始化设备,传入Framework回调接口 camera3_callback_ops_t |
| configure_streams | 配置数据流(预览、拍照、录像等),传入 camera3_stream_configuration_t |
| process_capture_request | 处理捕获请求,传入 camera3_capture_request_t |
| flush | 刷新所有未完成的请求,用于快速关闭 |
| dump | 导出调试信息 |
4.3.3 QCOM平台差异
- HAL3优先:QCOM平台默认使用HAL3,
camera3_device_t的ops指向qcamera3_device_ops实现。 - 私有数据:
priv指针指向qcamera3_device_t结构体,包含CHI(Camera Hardware Interface)上下文、pipeline句柄等。 - 兼容层:若Framework请求HAL1,QCOM通过
open_legacy返回包装后的camera_device_t。
4.4 camera3_stream_t:流配置
camera3_stream_t 描述一个数据流(如预览流、拍照流、录像流),定义在 camera3.h 中。它是 configure_streams 的核心参数。
4.4.1 结构体定义
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; // 旋转角度
int stream_set_id; // 流集合ID(用于同步)
int physical_camera_id; // 物理相机ID(逻辑相机使用)
} camera3_stream_t;
4.4.2 关键字段说明
| 字段 | 典型值 | 说明 |
|---|---|---|
| stream_type | CAMERA3_STREAM_OUTPUT | 输出流(预览/拍照/录像);输入流用于YUV reprocessing |
| format | HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED | QCOM平台常用此格式,由HAL选择最优格式 |
| usage | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_CAMERA_WRITE | 指示Gralloc分配内存时的用途 |
| max_buffers | 3 ~ 8 | HAL根据pipeline深度设置,Framework保证不超过此值 |
| data_space | HAL_DATASPACE_STANDARD_BT709 | 色彩空间,影响ISP处理 |
4.4.3 QCOM平台优化
- 格式协商:当Framework指定
IMPLEMENTATION_DEFINED时,QCOM HAL根据流用途选择最优格式(如预览用NV12,拍照用JPEG)。 - Buffer管理:
max_buffers由CHI pipeline的请求队列深度决定,通常为3~5。 - 物理相机ID:在逻辑相机(如双摄)中,
physical_camera_id指定该流属于哪个物理相机。
4.5 camera3_capture_request_t:捕获请求
camera3_capture_request_t 是Framework向HAL提交的每一次捕获请求,包含元数据、输出buffer和输入buffer(reprocessing时)。
4.5.1 结构体定义
typedef struct camera3_capture_request {
uint32_t frame_number; // 帧序号,单调递增
const camera3_stream_buffer_t *input_buffer; // 输入buffer(reprocessing)
uint32_t num_output_buffers; // 输出buffer数量
const camera3_stream_buffer_t *output_buffers; // 输出buffer数组
const camera_metadata_t *settings; // 捕获参数(AE/AWB/AF等)
uint32_t num_physcam_settings; // 物理相机参数数量
const camera_metadata_t **physcam_settings; // 物理相机参数数组
} camera3_capture_request_t;
4.5.2 关键字段说明
| 字段 | 说明 |
|---|---|
| frame_number | 全局递增帧号,用于追踪请求和结果 |
| input_buffer | 仅reprocessing时非空,如ZSL拍照的输入YUV buffer |
| output_buffers | 每个元素包含 stream、buffer、status、acquire_fence、release_fence |
| settings | 包含3A参数、AE区域、效果模式等,由Framework填充 |
| physcam_settings | 逻辑相机时,每个物理相机可独立设置参数 |
4.5.3 QCOM平台处理流程
- 接收请求:
process_capture_request被调用,HAL将请求加入CHI pipeline的请求队列。 - 解析settings:QCOM HAL将
camera_metadata_t转换为CHI内部的chi_metadata_t。 - Buffer管理:通过
acquire_fence等待buffer就绪,处理完成后通过release_fence通知Framework。 - 多帧处理:对于HDR、夜景等场景,一个请求可能触发多个帧的捕获,最终合成一个结果。
process_capture_request 必须在5ms内返回,否则会导致ANR。QCOM平台通过异步pipeline处理,避免在回调中执行耗时操作。
4.6 数据结构交互流程
下图展示了从 configure_streams 到 process_capture_request 的完整数据流,以及各结构体之间的协作关系。
4.7 数据结构对比总结
| 结构体 | 所属层级 | 核心职责 | QCOM平台关键点 |
|---|---|---|---|
| camera_module_t | 模块层 | 枚举设备、打开设备 | 通过 HAL_MODULE_INFO_SYM 导出,支持逻辑相机枚举 |
| camera_device_t | HAL1设备层 | 预览、拍照、录像(旧接口) | 仅用于兼容,QCOM通过 open_legacy 包装 |
| camera3_device_t | HAL3设备层 | 流配置、捕获请求处理 | priv 指向 qcamera3_device_t,包含CHI上下文 |
| camera3_stream_t | 流配置层 | 描述数据流属性 | 格式协商、max_buffers 由pipeline深度决定 |
| camera3_capture_request_t | 请求层 | 携带元数据和buffer | 异步处理,process_capture_request 需5ms内返回 |
camera3_device_t 是中枢,camera3_stream_t 和 camera3_capture_request_t 是数据载体。开发时重点关注 configure_streams 和 process_capture_request 的实现,它们是性能优化的主战场。