3. Camera HAL 关键数据结构详解

在 Camera HAL 开发与调试中,理解核心数据结构是定位问题的基石。本章深入剖析 camera_metadata、camera3_stream_t、camera3_capture_request_t 和 camera3_capture_result_t 四个关键结构体,涵盖其设计意图、字段含义、生命周期及调试要点。

3.1 camera_metadata:控制与元数据的通用容器

camera_metadata 是 Android Camera 框架中用于传递控制参数和结果元数据的核心数据结构。它采用序列化的键值对存储方式,支持高效的查找与更新。

核心特点:
  • 键值对存储: 每个条目由 tag(32位整数标识符)、类型、计数和数据组成。
  • 两种类型: camera_metadata_t(可变,用于构建请求)和 const camera_metadata_t(不可变,用于结果)。
  • 调试价值: 超过 90% 的 HAL 问题可通过检查 metadata 中的关键 tag 定位。

3.1.1 数据结构布局

// camera_metadata 内部布局(简化示意)
typedef struct camera_metadata {
    size_t          size;           // 总大小
    uint32_t        version;        // 版本号
    uint32_t        flags;          // 标志位
    size_t          entry_count;    // 当前条目数
    size_t          entry_capacity; // 最大条目容量
    size_t          data_count;     // 当前数据项数
    size_t          data_capacity;  // 最大数据容量
    uint8_t*        entries;        // 条目数组起始地址
    uint8_t*        data;           // 数据缓冲区起始地址
} camera_metadata_t;

3.1.2 常用操作与调试接口

操作 函数 调试场景
查找条目 camera_metadata_find() 确认某个 tag 是否被正确设置
更新条目 camera_metadata_update() 修改 AE/AWB 参数后验证写入
序列化/反序列化 camera_metadata_encode() / decode() 跨进程传递时检查数据完整性
打印内容 dump_camera_metadata() 全量输出 metadata 用于日志分析
调试技巧: 在 HAL 的 process_capture_request 和 process_capture_result 入口处调用 dump_camera_metadata(),对比请求与结果中的关键 tag(如 ANDROID_SENSOR_EXPOSURE_TIME、ANDROID_CONTROL_AE_MODE),可快速发现参数丢失或未生效问题。

3.2 camera3_stream_t:图像数据流的管道定义

camera3_stream_t 定义了从 HAL 到框架的图像数据流属性。每个流对应一个特定的消费者(如预览 Surface、拍照 JPEG 编码器、视频编码器)。

3.2.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;    // HAL 可同时持有的最大 buffer 数
    void*    priv;           // HAL 私有数据指针
    int      rotation;       // 输出旋转角度
    int      physical_camera_id; // 多摄场景下的物理 camera ID
} camera3_stream_t;

3.2.2 流配置与调试要点

字段 常见值 调试关注点
stream_type CAMERA3_STREAM_OUTPUT 确认流方向是否正确(输出 vs 输入)
format HAL_PIXEL_FORMAT_YCbCr_420_888 格式不匹配会导致 buffer 填充错误
usage GRALLOC_USAGE_HW_TEXTURE 检查 GPU/显示/编码器使用标志是否遗漏
max_buffers 3 ~ 8 值过小可能导致 dequeue 阻塞
常见陷阱: priv 指针由 HAL 管理,但框架不会自动释放。在 configure_streams 被再次调用时,务必先清理旧流关联的私有资源,否则会造成内存泄漏或野指针。

3.3 camera3_capture_request_t:一次捕获的完整指令

该结构体封装了 HAL 执行一次图像捕获所需的所有信息:目标流、输入 buffer、控制参数和设置。

3.3.1 结构体定义

typedef struct camera3_capture_request {
    uint32_t                frame_number;   // 帧序号,单调递增
    const camera_metadata_t* settings;      // 本次捕获的控制参数
    size_t                  num_output_buffers; // 输出 buffer 数量
    const camera3_stream_buffer_t* output_buffers; // 输出 buffer 数组
    const camera3_stream_buffer_t* input_buffer;   // 输入 buffer(ZSL/ reprocess 时使用)
} camera3_capture_request_t;

3.3.2 请求生命周期与调试

  1. 创建: CameraService 根据应用请求构建 request,填充 settings 和 output_buffers。
  2. 下发: 通过 process_capture_request 传递给 HAL。
  3. 处理: HAL 解析 settings,驱动 sensor 曝光,ISP 处理,填充 output_buffers。
  4. 返回: HAL 通过 process_capture_result 返回结果。
调试关键点:
  • frame_number 连续性: 检查是否有跳号或重复,可发现 HAL 内部丢帧或重复处理问题。
  • settings 指针有效性: 确认 settings 在 HAL 处理期间未被框架释放或修改。
  • output_buffers 状态: 每个 buffer 的 status 字段在返回时必须正确设置(CAMERA3_BUFFER_STATUS_OK 或 ERROR)。

3.4 camera3_capture_result_t:捕获结果的完整汇报

HAL 通过该结构体将处理完成的帧结果返回给框架,包含 metadata、输出 buffer 和错误信息。

3.4.1 结构体定义

typedef struct camera3_capture_result {
    uint32_t                frame_number;       // 对应请求的帧序号
    const camera_metadata_t* result;            // 结果 metadata(AE/AWB/传感器参数等)
    size_t                  num_output_buffers; // 返回的输出 buffer 数量
    const camera3_stream_buffer_t* output_buffers; // 输出 buffer 数组
    uint32_t                partial_result;     // 部分结果序号(用于分阶段返回)
} camera3_capture_result_t;

3.4.2 部分结果机制

HAL 可以分多次返回同一个 frame_number 的结果,通过 partial_result 字段标识阶段:

partial_result 值 含义 典型内容
1 第一阶段结果 传感器 metadata(曝光、增益、时间戳)
2 第二阶段结果 3A 状态、统计信息
… 后续阶段 输出 buffer 就绪
0 最终结果 所有 buffer 和 metadata 完整返回
调试建议: 在 HAL 中记录每个 frame_number 的 partial_result 到达时间和内容。如果框架长时间未收到最终结果(partial_result=0),通常是 HAL 未释放 buffer 或 metadata 构造出错。

3.5 数据结构关系总览

下图展示了四个关键数据结构在一次完整 capture 流程中的交互关系:

Camera HAL 关键数据结构交互关系 camera_metadata (settings / result) camera3_stream_t (流定义) camera3_capture_request_t frame_number + settings + output_buffers camera3_capture_result_t frame_number + result + output_buffers HAL process_capture_request() result metadata 说明:request 携带 settings 和 stream 信息进入 HAL,HAL 处理后通过 result 返回 metadata 和填充后的 buffer

3.6 调试实战:常见问题与数据结构关联

现象 可能原因 涉及数据结构 检查方法
预览黑屏 output_buffers 未正确填充或 status 错误 camera3_stream_buffer_t 检查 buffer handle 和 release fence
拍照曝光异常 settings 中 AE 参数未生效 camera_metadata 对比 request 和 result 中的 AE tag
帧率不稳定 frame_number 不连续或 partial_result 超时 camera3_capture_request_t / result_t 打印 frame_number 序列和时间戳
应用崩溃 stream 配置与 buffer 格式不匹配 camera3_stream_t 验证 format 和 usage 字段一致性
总结: 四个数据结构构成了 Camera HAL 与框架之间的通信契约。调试时,建议在 HAL 的入口和出口处统一记录这些结构体的关键字段,形成“请求-处理-结果”的完整日志链路,这是快速定位问题的核心方法。