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 信息时
camera3_device_t 与 Framework 交互关系 Camera Framework (CameraService) camera3_device_t ops / priv HAL 实现 (Vendor 代码) camera3_device_ops_t 核心操作 • initialize(callback_ops) —— 注册回调接口 • configure_streams(stream_list) —— 配置流 • process_capture_request(request) —— 处理请求 • flush() —— 清空请求队列

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 不能持有对缓冲区的引用。
camera3_callback_ops_t 回调流程 HAL 实现 callback_ops Framework 回调数据传递 ① process_capture_result(result) —— 传递 metadata + 输出缓冲区 + 部分结果标识 ② notify(msg) —— 传递错误码 (ERROR_REQUEST/ERROR_RESULT/ERROR_DEVICE) 或快门事件 ③ 两个回调都必须在 HAL 的工作线程中调用,Framework 保证回调本身是线程安全的

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 标志兼容。
camera3_stream_t 配置与硬件资源映射 Framework 配置 • stream_type: OUTPUT • width: 1920, height: 1080 • format: YCbCr_420_888 HAL 填充字段 • usage: GRALLOC_USAGE_HW_... • max_buffers: 4 • priv: 指向内部流上下文 硬件资源分配 • ISP 管线配置 • 内存池分配 • 时钟与带宽设置 流配置关键约束 • HAL 不能修改 width/height/format/stream_type,只能填充 usage/max_buffers/priv • max_buffers 表示 HAL 同时需要的缓冲区数量,Framework 会据此分配 buffer pool • 如果 HAL 不支持请求的配置,必须在 configure_streams() 中返回 -EINVAL

2.4 三者协作关系总结

在 CaptureRequest 的完整生命周期中,三个结构体按照以下顺序协作:

  1. 设备打开: Framework 通过 HAL 模块获取 camera3_device_t 实例。
  2. 初始化: Framework 调用 ops->initialize(),传入 camera3_callback_ops_t 回调接口。
  3. 流配置: Framework 调用 ops->configure_streams(),传入 camera3_stream_t 数组,HAL 填充 usage、max_buffers 等字段。
  4. 请求处理: Framework 调用 ops->process_capture_request(),HAL 处理完成后通过 camera3_callback_ops_t 返回结果。
  5. 错误处理: 发生异常时,HAL 通过 notify() 回调上报错误信息。
最佳实践: 在实现 HAL 时,建议将 camera3_device_t 的 priv 字段指向一个包含所有设备状态(包括流列表、回调指针、内部线程句柄)的上下文结构体。这样可以避免使用全局变量,提高代码的可维护性和线程安全性。