3. Camera HAL3 核心数据结构详解

Camera HAL3 接口的设计围绕四个核心数据结构展开:camera3_device_t、camera3_callback_ops_t、camera3_stream_t 和 camera3_capture_request_t。这四个结构体构成了 HAL3 与 Camera Service 之间通信的契约基础,理解它们是开发稳定、高性能 Camera HAL 的必修课。

学习提示: 本章节所有结构体定义均基于 Android 14 (API 34) 的 hardware/libhardware/include/hardware/camera3.h 头文件。不同 Android 版本可能存在细微差异,但核心字段保持一致。

3.1 camera3_device_t:HAL 设备句柄

camera3_device_t 是 Camera Service 与 HAL 交互的入口点,代表一个物理或逻辑摄像头设备。它继承自 hw_device_t,并扩展了 HAL3 特有的操作函数指针。

typedef struct camera3_device {
    hw_device_t common;
    camera3_device_ops_t *ops;
    void *priv;
} camera3_device_t;
字段 类型 说明
common hw_device_t 标准硬件设备结构体,包含 tag、version、module、close 等基础字段
ops camera3_device_ops_t * 指向操作函数表的指针,包含 initialize、configure_streams、process_capture_request 等核心方法
priv void * HAL 私有数据指针,通常指向自定义的设备上下文结构体
实战要点: 在 open() 回调中,HAL 需要为每个摄像头实例分配并初始化 camera3_device_t。priv 字段通常指向一个包含传感器信息、流配置状态、请求队列等运行时数据的上下文结构体。切勿在 ops 返回后修改 common 字段,否则会导致 Service 端崩溃。
camera3_device_t 内存布局与关联关系 camera3_device_t common: hw_device_t ├ tag = HARDWARE_DEVICE_TAG ├ version = HARDWARE_HAL_API_V2 └ close() ops: camera3_device_ops_t * priv: void * camera3_device_ops_t initialize() configure_streams() register_stream_buffers() process_capture_request() get_metadata_vendor_tag_ops() dump() flush() signal_stream_flush() HAL 私有上下文 sensor_info stream_configs request_queue callback_ops 说明:camera3_device_t 通过 ops 指针调用 HAL 实现,通过 priv 指针访问 HAL 内部状态。

3.2 camera3_callback_ops_t:异步回调契约

当 Camera Service 调用 initialize() 时,会传入一个 camera3_callback_ops_t 结构体指针。HAL 通过这个结构体向 Service 异步通知事件、返回结果数据和发送信号。

typedef struct camera3_callback_ops {
    void (*process_capture_result)(const struct camera3_callback_ops *,
                                   const camera3_capture_result_t *);
    void (*notify)(const struct camera3_callback_ops *,
                   const camera3_notify_msg_t *);
    void (*process_capture_result_with_flags)(const struct camera3_callback_ops *,
                                              const camera3_capture_result_t *,
                                              uint32_t flags);
} camera3_callback_ops_t;
回调函数 触发时机 关键参数
process_capture_result HAL 完成一次 capture request 的部分或全部处理 camera3_capture_result_t:包含 frame_number、结果 metadata、输出 buffer、partial_result 等
notify 发生异步事件(如曝光结束、快门、错误) camera3_notify_msg_t:包含消息类型(ERROR、SHUTTER 等)及对应数据
process_capture_result_with_flags Android 14+ 新增,带标志位的结果返回 flags:如 CAMERA3_RESULT_FLAG_FINAL 表示该 request 的所有结果已返回完毕
常见错误: HAL 必须在 同一个线程 中按 frame_number 递增顺序调用 process_capture_result。乱序返回会导致 Service 端 buffer 管理混乱,引发 ANR 或黑屏。notify 中的 SHUTTER 事件必须在对应的 process_capture_result 之前或同时发出。
camera3_callback_ops_t 异步回调时序 Camera Service Camera HAL initialize(callback_ops) notify(SHUTTER, frame_number) process_capture_result(result) notify(ERROR_REQUEST, frame_number) 关键规则:SHUTTER 通知必须在 process_capture_result 之前或同时发出;ERROR 通知后该 frame 不再返回结果。

3.3 camera3_stream_t:数据流管道

camera3_stream_t 描述一条从 HAL 到 Consumer(如 SurfaceView、ImageReader、MediaCodec)的数据流。在 configure_streams() 中,Service 向 HAL 传递一个流数组,HAL 需要验证并配置这些流。

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;
    const camera_metadata_t *stream_configuration;
    const camera_metadata_t *stream_parameters;
    void *priv;
    int data_space;            // HAL_DATASPACE_xxx
    int rotation;              // CAMERA3_STREAM_ROTATION_xxx
    const char *physical_camera_id;
    uint64_t buffer_size;
    int vndk_version;
} camera3_stream_t;
字段 设置方 说明
stream_type Service CAMERA3_STREAM_OUTPUT(输出到 Surface)、CAMERA3_STREAM_INPUT(输入,如 reprocessing)、CAMERA3_STREAM_BIDIRECTIONAL(双向,如 ZSL)
width / height / format Service 分辨率与像素格式。HAL 可在 configure_streams 中修改为更接近的值
max_buffers HAL 填写 HAL 在该流上同时需要的 buffer 最大数量,Service 据此分配 buffer 池
priv HAL 填写 HAL 私有数据,通常指向该流对应的硬件 DMA 通道或 ISP 输入输出配置
usage Service Gralloc buffer 的使用标志,如 GRALLOC_USAGE_HW_CAMERA_WRITE、GRALLOC_USAGE_HW_TEXTURE
实战要点: HAL 在 configure_streams() 中必须检查所有流的组合是否可行。例如,同时请求 4K 60fps 输出流 + 1080p 输入流时,需要确认 ISP 带宽是否足够。如果组合不可行,返回 -EINVAL 并建议替代方案。max_buffers 的典型值为 3~6,过小会导致 dequeue 阻塞,过大会增加内存压力。
camera3_stream_t 流配置与数据流向 Camera HAL ISP / 传感器驱动 3A 算法引擎 Buffer 管理 输出流: Preview 1920x1080, NV12 max_buffers=4 输出流: Video 3840x2160, NV12 max_buffers=6 输入流: Reprocess 1920x1080, YV12 max_buffers=3 Consumer 端 SurfaceView (Preview) MediaCodec (Video Encode) ImageReader (Snapshot) Reprocess Input ZSL 环形 Buffer 说明:HAL 通过 configure_streams() 接收流数组,每个流独立配置 max_buffers 和 priv 上下文。

3.4 camera3_capture_request_t:一次捕获的完整描述

每次拍照或预览帧的请求都由 camera3_capture_request_t 描述。Service 通过 process_capture_request() 将请求下发到 HAL,HAL 解析后驱动传感器曝光、ISP 处理并最终返回结果。

typedef struct camera3_capture_request {
    uint32_t frame_number;
    const camera_metadata_t *settings;
    camera3_stream_buffer_t *input_buffer;
    uint32_t num_input_buffers;
    camera3_stream_buffer_t *output_buffers;
    uint32_t num_output_buffers;
    const camera_metadata_t *physical_camera_settings;
    int32_t *physcam_id;
    uint32_t num_physcam_settings;
} camera3_capture_request_t;
字段 说明
frame_number 单调递增的帧序号,从 1 开始。HAL 必须在返回结果和通知中携带相同的 frame_number
settings 本次请求的完整 metadata,包含 AE/AWB/AF 模式、sensitivity、exposure_time、effect 等控制参数
input_buffer 仅 reprocessing 请求使用,指向输入 buffer(如 ZSL 环形 buffer 中的一帧)
output_buffers 输出 buffer 数组,每个 buffer 对应一个已配置的 stream。HAL 将处理后的数据填入这些 buffer
physical_camera_settings 逻辑摄像头(multi-camera)中,为每个物理摄像头单独指定的 metadata 覆盖
关键约束: HAL 必须在收到 process_capture_request 后尽快返回,不能在该函数内部阻塞等待传感器曝光完成。正确的做法是:将请求加入内部队列,由独立的工作线程异步处理。如果 HAL 在 process_capture_request 中阻塞超过 500ms,Service 会触发 watchdog 并杀死 HAL 进程。
camera3_capture_request_t 处理流程 Camera Service process_capture_request() HAL 主线程 快速入队,立即返回 内部请求队列 HAL 工作线程 传感器曝光 + ISP 处理 process_capture_result() camera3_capture_request_t frame_number = 42 settings = {AE_ON, AWB_AUTO, ...} output_buffers[0] → Preview output_buffers[1] → Video num_output_buffers = 2 input_buffer = NULL num_input_buffers = 0 physical_camera_settings = NULL physcam_id = NULL num_physcam_settings = 0 关键设计:process_capture_request 必须非阻塞返回,实际工作在独立线程中完成,通过回调异步返回结果。

3.5 四个核心结构体的协作关系

在实际的 Camera HAL 实现中,这四个结构体通过以下时序协作完成一次完整的拍照或预览流程:

  1. 初始化阶段: Service 调用 open() 获取 camera3_device_t,然后调用 ops->initialize() 传入 camera3_callback_ops_t。
  2. 流配置阶段: Service 调用 ops->configure_streams() 传入 camera3_stream_t 数组,HAL 验证并设置 max_buffers 和 priv。
  3. 请求下发阶段: Service 构造 camera3_capture_request_t,调用 ops->process_capture_request() 下发。
  4. 结果返回阶段: HAL 通过 callback_ops->notify() 发送 SHUTTER 事件,通过 callback_ops->process_capture_result() 返回填充好的 buffer 和 metadata。
阶段 核心结构体 关键函数 HAL 职责
初始化 camera3_device_t open() → initialize() 分配设备上下文,保存 callback_ops 指针
流配置 camera3_stream_t configure_streams() 验证流组合,设置 max_buffers 和 priv
请求处理 camera3_capture_request_t process_capture_request() 非阻塞入队,异步执行传感器曝光和 ISP 处理
结果回调 camera3_callback_ops_t notify() / process_capture_result() 按序返回结果,保证 SHUTTER 先于结果
进阶思考: 在 multi-camera 场景下,一个逻辑 camera3_device_t 可能对应多个物理传感器。此时 physical_camera_settings 字段允许为每个物理摄像头指定独立的 AE/AWB 参数。HAL 需要将逻辑请求拆解为多个物理请求,分别驱动对应传感器,最后合成一个结果返回。
四个核心结构体完整协作时序 时间 t1 t2 t3 t4 ← 上一章 📖 返回目录 下一章 →