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

Camera HAL3 的设计围绕一套精炼的数据结构展开,它们是 HAL 层与 Camera Service 之间通信的契约。掌握这些结构是理解 HAL3 运作机制的基础。本章将深入剖析 camera3_device_t、camera3_callback_ops_t、camera3_stream_t 和 camera3_capture_request_t 这四大核心数据结构。

4.1 camera3_device_t:HAL 设备实例

camera3_device_t 是 HAL3 设备在 Camera Service 中的抽象表示。它继承自 Android 硬件抽象层的通用设备结构 hw_device_t,并扩展了 Camera HAL3 特有的操作接口。每一个打开的 Camera 设备(如后置摄像头)都对应一个 camera3_device_t 实例。

关键角色: 它是 Camera Service 与 HAL 实现之间的主要交互点。Service 通过调用该结构体中的函数指针来下发配置、请求和进行控制。

4.1.1 结构体定义与核心字段

typedef struct camera3_device {
    hw_device_t common;                     // 继承自通用硬件设备结构
    camera3_device_ops_t *ops;              // 指向设备操作函数集的指针
    void *priv;                             // HAL 私有数据指针,由 HAL 实现管理
} camera3_device_t;
字段 类型 说明
common hw_device_t 标准硬件设备结构,包含版本号、模块 ID、close 函数指针等。
ops camera3_device_ops_t* 指向 camera3_device_ops_t 结构体的指针,该结构体包含了所有 HAL3 设备操作函数,如 initialize、configure_streams、process_capture_request 等。
priv void* HAL 实现可以在此指针上挂载自己的私有上下文数据,例如设备状态、传感器信息等。

4.1.2 设备操作函数集 (camera3_device_ops_t)

camera3_device_ops_t 是 HAL3 的核心操作接口,它定义了 Camera Service 可以调用的所有功能。以下是最关键的几个函数:

  • initialize:在设备打开后调用,用于初始化 HAL 设备,并注册回调函数。
  • configure_streams:配置 Camera 的输入/输出流,是建立数据管道的核心步骤。
  • process_capture_request:提交一个捕获请求,HAL 需要处理该请求并返回结果。
  • flush:清空所有正在处理的请求,用于快速停止或重置设备。
  • dump:导出 HAL 设备的调试信息。
实现要点: 在实现 camera3_device_t 时,务必正确初始化 common.tag、common.version 和 common.close 回调。错误的版本号会导致 Service 拒绝加载 HAL。
camera3_device_t 结构关系 camera3_device_t HAL 设备实例 hw_device_t common camera3_device_ops_t *ops void *priv initialize() configure_streams() process_capture_request() flush()

4.2 camera3_callback_ops_t:异步回调接口

Camera HAL3 是一个异步系统。当 HAL 处理完一个请求或产生事件时,它不能直接调用 Service 的内部方法,而是通过 camera3_callback_ops_t 结构体中注册的回调函数来通知 Service。这个结构体由 Camera Service 实现,并在 initialize() 时传递给 HAL。

4.2.1 核心回调函数

回调函数 触发时机 关键参数
process_capture_result 当 HAL 完成一个捕获请求的处理时 camera3_capture_result_t *result:包含元数据、输出 buffer 等
notify 当发生异步事件时(如快门、错误) camera3_notify_msg_t *msg:事件类型和具体数据

4.2.2 回调机制的重要性

  • 解耦:HAL 不需要知道 Service 的内部实现细节,只需调用函数指针。
  • 异步性:HAL 可以在自己的线程中处理完请求后,通过回调返回结果,不会阻塞 Service。
  • 生命周期管理:Service 通过 notify 回调中的 CAMERA3_MSG_ERROR 事件来感知 HAL 层的错误,并进行恢复或销毁操作。
常见陷阱: HAL 实现必须在调用 process_capture_result 或 notify 后尽快释放对 buffer 和元数据的所有权。Service 期望在回调返回后,这些资源可以被回收或复用。延迟释放会导致 buffer 泄漏和性能下降。
camera3_callback_ops_t 异步回调流程 Camera Service (回调实现者) HAL Device (回调调用者) 1. initialize(callback_ops) 注册回调 2. process_capture_request() 3. process_capture_result()

4.3 camera3_stream_t:数据流描述

camera3_stream_t 描述了一个 Camera 数据流的属性。它定义了图像的格式、尺寸、用途以及 HAL 和 Service 之间传递 buffer 的方式。在 configure_streams() 阶段,Service 会创建一个或多个 camera3_stream_t 实例,并传递给 HAL 进行配置。

4.3.1 核心字段解析

字段 类型 说明
stream_type int 流类型:CAMERA3_STREAM_OUTPUT (输出)、CAMERA3_STREAM_INPUT (输入)、CAMERA3_STREAM_BIDIRECTIONAL (双向)。
width / height uint32_t 图像的像素宽度和高度。
format int 像素格式,如 HAL_PIXEL_FORMAT_YCbCr_420_888、HAL_PIXEL_FORMAT_BLOB (用于 JPEG) 等。
usage uint32_t Gralloc 使用标志,描述了 buffer 的预期用途(如 CPU 读、GPU 纹理、视频编码器)。
max_buffers uint32_t HAL 为该流请求的最大同时使用的 buffer 数量。
priv void* HAL 私有指针,可用于关联流特定的上下文。

4.3.2 流配置流程

  1. Service 创建流数组:根据应用层的需求(如预览、拍照、录像)创建 camera3_stream_t 数组。
  2. 调用 configure_streams():Service 将流数组传递给 HAL。
  3. HAL 验证并调整:HAL 检查流参数是否支持,并可以修改 usage、max_buffers 和 format 字段。
  4. 分配 buffer:配置完成后,Service 和 HAL 通过 Gralloc 分配器为这些流分配实际的图形 buffer。
性能优化: max_buffers 字段是 HAL 向 Service 请求的 buffer 池深度。设置过小会导致 pipeline 饥饿,设置过大会增加内存占用。通常,预览流设置为 3-4 个 buffer,拍照流可以设置为 1-2 个。
camera3_stream_t 配置与数据流向 Camera Service HAL Device camera3_stream_t stream_type: OUTPUT width: 1920, height: 1080 format: YCbCr_420_888 usage: GRALLOC_USAGE_HW_VIDEO_ENCODER max_buffers: 4 配置流 验证/调整 Buffer 消费者 Buffer 生产者 填充数据

4.4 camera3_capture_request_t:捕获请求

每一个拍照或预览帧的请求都由 camera3_capture_request_t 结构体描述。它包含了 HAL 处理一帧图像所需的所有信息:目标流、元数据、输入 buffer 等。Service 通过 process_capture_request() 将请求提交给 HAL。

4.4.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;      // 请求的元数据 (3A 参数等)
    uint32_t num_physcam_settings;          // 物理相机设置数量 (多摄)
    const camera_metadata_t **physcam_settings; // 物理相机设置数组
} camera3_capture_request_t;

4.4.2 请求生命周期

  1. 创建:Service 根据应用层的请求(如点击拍照按钮)创建一个 camera3_capture_request_t 实例。
  2. 填充:Service 填充帧序号、输出 buffer 列表(从对应流的 buffer 池中取出)、以及包含 AE/AWB/AF 等参数的元数据。
  3. 提交:Service 调用 process_capture_request() 将请求发送给 HAL。
  4. 处理:HAL 解析请求,驱动 ISP 进行图像处理,并将结果填充到输出 buffer 中。
  5. 返回:HAL 通过 process_capture_result() 回调将填充好的 buffer 和结果元数据返回给 Service。
关键约束: HAL 必须保证 frame_number 的唯一性和递增性。Service 使用 frame_number 来匹配请求和结果。如果 HAL 丢弃了一个请求,它必须通过 notify() 回调发送一个 CAMERA3_MSG_ERROR_REQUEST 错误消息。
camera3_capture_request_t 处理流程 1. 创建请求 填充请求内容 frame_number: 42 output_buffers[0] settings: {AE, AWB, AF} 3. process_capture_request() 4. HAL 处理 5. process_capture_result() 6. Service 接收结果

4.5 数据结构关系总结

这四种数据结构共同构成了 HAL3 的通信骨架:

  • camera3_device_t 是通信的端点,提供了操作入口。
  • camera3_callback_ops_t 是反向通道,用于异步通知。
  • camera3_stream_t 定义了数据的格式和流向。
  • camera3_capture_request_t 是驱动数据流动的指令单元。
学习建议: 在阅读或编写 HAL 代码时,建议从 camera3_device_ops_t 中的 configure_streams 和 process_capture_request 函数入手,跟踪这些数据结构的创建、传递和销毁过程,可以快速理解 HAL3 的整体数据流。