4. HAL3核心数据结构:camera3_device_t、camera3_callback_ops_t、camera3_stream_t详解
在HAL3架构中,camera3_device_t、camera3_callback_ops_t和camera3_stream_t是驱动与框架交互的三大核心数据结构。它们分别定义了设备操作接口、异步回调契约以及数据流配置规范。理解这三者的关系与字段含义,是进行高通平台HAL3适配的首要前提。
学习提示: 本章节将逐一拆解这三个结构体的成员变量与函数指针,并结合高通平台的实际适配场景,说明每个字段在初始化、配置和运行时的作用。
4.1 camera3_device_t:设备操作接口
camera3_device_t 是HAL3中代表单个Camera设备的结构体,它继承自 hw_device_t,并扩展了HAL3特有的操作函数指针。框架通过该结构体调用底层驱动完成初始化、配置流、捕获请求等核心操作。
核心要点: camera3_device_t 是框架与HAL3设备之间的“命令通道”,所有同步操作均通过其函数指针下发。
4.1.1 结构体定义与关键字段
typedef struct camera3_device {
hw_device_t common; // 继承自硬件抽象层基础结构
camera3_device_ops_t *ops; // 操作函数指针集合
void *priv; // 私有数据指针,指向高通平台的自定义设备上下文
} camera3_device_t;
| 字段 | 类型 | 说明 | 高通适配要点 |
|---|---|---|---|
| common | hw_device_t | 包含设备版本号、模块ID、open/close等基础接口 | 需正确填充 tag 和 version,版本号必须为 HARDWARE_DEVICE_API_VERSION(3, 0) |
| ops | camera3_device_ops_t* | 指向所有HAL3操作函数的指针结构体 | 必须实现所有非NULL函数指针,否则框架拒绝加载 |
| priv | void* | 私有数据,通常指向高通 qcamera_device_t 扩展结构 |
用于存储底层驱动句柄、传感器信息、流列表等 |
4.1.2 camera3_device_ops_t 核心函数指针
camera3_device_ops_t 是实际干活的地方,包含以下关键函数指针:
- initialize:传入
camera3_callback_ops_t,建立框架到HAL的回调通道。 - configure_streams:接收
camera3_stream_configuration_t,配置数据流管道。 - process_capture_request:接收
camera3_capture_request_t,下发拍照/预览请求。 - flush:清空所有未处理的请求,用于快速停止。
- dump:导出设备调试信息。
避坑指南: 在高通平台上,
configure_streams 的返回值直接影响后续请求能否正常下发。如果返回 BAD_VALUE,框架会认为流配置无效并终止Camera打开流程。务必检查流参数(如宽高、格式)是否在传感器支持范围内。
4.2 camera3_callback_ops_t:异步回调契约
camera3_callback_ops_t 是框架注册给HAL3设备的回调函数集合。HAL3驱动通过这些回调将结果数据、事件和缓冲区异步通知给框架。它是HAL3“异步管道”模型的核心纽带。
核心要点: 回调函数由框架实现,HAL3驱动只能调用不能修改。回调的调用顺序和线程安全由HAL3驱动负责。
4.2.1 结构体定义与回调函数
typedef struct camera3_callback_ops {
void (*process_capture_result)(const struct camera3_callback_ops *ops,
const camera3_capture_result_t *result);
void (*notify)(const struct camera3_callback_ops *ops,
const camera3_notify_msg_t *msg);
} camera3_callback_ops_t;
| 回调函数 | 触发时机 | 传递数据 | 高通平台注意事项 |
|---|---|---|---|
| process_capture_result | 捕获请求完成(部分或全部) | camera3_capture_result_t:包含输出缓冲区、元数据、部分结果标记 | 必须按请求的 frame_number 顺序回调,乱序会导致ANR |
| notify | 错误、快门事件、请求错误等 | camera3_notify_msg_t:包含错误码、帧号、事件类型 | 错误通知必须及时,否则框架会超时强制关闭设备 |
4.2.2 回调调用流程
以下SVG图展示了从请求下发到回调返回的完整异步流程:
4.3 camera3_stream_t:数据流配置
camera3_stream_t 描述单个数据流的属性,包括图像格式、分辨率、使用方向等。在 configure_streams 调用中,框架会传入一个 camera3_stream_t 数组,HAL3驱动需要根据这些配置分配内部缓冲区并设置ISP管道。
核心要点: camera3_stream_t 是HAL3“流配置”的最小单元,每个流对应一个输出目标(如预览Surface、拍照ImageReader、录像MediaCodec)。
4.3.1 结构体定义与关键字段
typedef struct camera3_stream {
int stream_type; // CAMERA3_STREAM_OUTPUT / INPUT / BIDIRECTIONAL
uint32_t width; // 图像宽度(像素)
uint32_t height; // 图像高度(像素)
int format; // 像素格式(HAL_PIXEL_FORMAT_xxx)
uint32_t usage; // 使用标志(GRALLOC_USAGE_xxx)
uint32_t max_buffers; // HAL3驱动请求的最大缓冲区数
const char *physical_camera_id; // 物理Camera ID(多摄场景)
void *priv; // 私有数据,高通用于存储stream句柄
uint64_t reserved[7]; // 保留字段
} camera3_stream_t;
| 字段 | 说明 | 高通适配典型值/注意事项 |
|---|---|---|
| stream_type | 流方向:输出、输入或双向 | 预览/拍照通常为 CAMERA3_STREAM_OUTPUT |
| width / height | 图像分辨率 | 必须匹配传感器输出尺寸,否则 configure_streams 返回错误 |
| format | 像素格式 | 常用 HAL_PIXEL_FORMAT_YCbCr_420_888(预览)和 HAL_PIXEL_FORMAT_BLOB(JPEG) |
| usage | Gralloc缓冲区使用标志 | 预览通常为 GRALLOC_USAGE_SW_READ_OFTEN,录像为 GRALLOC_USAGE_HW_VIDEO_ENCODER |
| max_buffers | HAL请求的缓冲区数量 | 高通平台通常请求3~4个缓冲区用于双缓冲或三缓冲 |
4.3.2 流配置与管道关系
以下SVG图展示了一个典型预览+拍照场景下的流配置结构:
4.4 三者协作关系
在HAL3运行时,camera3_device_t、camera3_callback_ops_t和camera3_stream_t通过以下方式协作:
- 初始化阶段:框架调用
camera3_device_t->ops->initialize(),传入camera3_callback_ops_t指针,HAL3驱动保存该指针用于后续回调。 - 配置阶段:框架调用
configure_streams(),传入camera3_stream_configuration_t(包含camera3_stream_t数组),HAL3驱动解析流参数并配置ISP。 - 运行阶段:框架下发
process_capture_request,HAL3驱动填充输出缓冲区,通过process_capture_result回调返回结果。
高通平台经验: 在
configure_streams 中,高通HAL会检查所有流的 format 和 usage 是否匹配硬件能力。如果预览流和拍照流的分辨率差异过大,可能需要启用“双ISP”模式,此时 max_buffers 需要相应增加。
4.5 常见适配问题与排查
| 问题现象 | 可能原因 | 排查方向 |
|---|---|---|
| Camera打开失败 | camera3_device_t 的 common.version 不匹配 |
检查版本号是否为 HARDWARE_DEVICE_API_VERSION(3, 0) |
| 预览黑屏 | camera3_stream_t 的 format 或 usage 与Gralloc分配不匹配 |
确认 HAL_PIXEL_FORMAT_YCbCr_420_888 对应的usage包含 GRALLOC_USAGE_SW_READ_OFTEN |
| 拍照卡死 | process_capture_result 回调未按帧号顺序调用 | 检查驱动侧结果队列是否按 frame_number 排序 |
| ANR超时 | notify 回调未及时上报错误事件 | 在驱动检测到硬件错误时立即调用 notify(CAMERA3_MSG_ERROR_DEVICE) |
关键提醒: 在高通SDM平台(如SM8250)上,
camera3_stream_t 的 priv 字段被用于存储 cpp_stream_t 指针,用于连接ISP输出和JPEG编码器。切勿在框架侧修改该字段,否则会导致内存损坏。