Android Camera HAL架构从原理到实战项目 - 第3节

3.1 HAL3 设计理念:从 HAL1 到 HAL3 的演进

Android Camera HAL3 架构的核心设计理念是 “流水线化” 与 “请求-响应” 模型。与 HAL1 的同步、阻塞式操作不同,HAL3 允许应用层同时提交多个捕获请求(Capture Request),硬件抽象层可以并行处理这些请求,并按照完成顺序返回结果。这种设计大幅提升了多摄像头协同、高帧率连拍和复杂后处理场景的性能。

设计目标: 将 Camera 子系统从“黑盒”变为“可编程管线”,让应用层能够精确控制每一帧的传感器、ISP、后处理参数。

3.1.1 HAL1 vs HAL3 核心差异

对比维度 HAL1 HAL3
操作模型 同步、阻塞式 异步、流水线式
帧控制粒度 粗粒度(预览/拍照/录像模式切换) 逐帧精细控制(曝光、增益、对焦、AE/AWB 锁定等)
多摄像头支持 逻辑摄像头映射复杂 原生支持物理摄像头组与逻辑摄像头
输出流数量 通常 1~2 路 支持多路并行输出(YUV、RAW、HEIC、Depth 等)
Buffer 管理 HAL 内部管理 Gralloc + 框架统一管理,支持 Buffer 复用
关键理解: HAL3 将 Camera 从“设备驱动”提升为“图像处理引擎”,每一帧都是一个独立的“任务”,包含完整的 3A 参数、输出流规格和后处理配置。

3.2 Camera3Module:模块入口与设备管理

camera3_module_t 是 HAL3 的顶层入口结构体,由 HAL 库导出。框架通过 open() 方法获取 camera3_device_t 实例,进而操作具体的 Camera 设备。

// hardware/libhardware/include/hardware/camera3.h
typedef struct camera3_module {
    hw_module_t common;
    int (*get_number_of_cameras)(void);
    int (*get_camera_info)(int camera_id, struct camera_info *info);
    int (*set_callbacks)(const camera3_callback_ops_t *callbacks);
    void (*get_vendor_tag_ops)(vendor_tag_ops_t *ops);
    int (*open_legacy)(const struct hw_module_t* module, const char* id,
                       uint32_t halVersion, struct hw_device_t** device);
    // ... 其他扩展接口
} camera3_module_t;

3.2.1 Module 核心职责

  • 设备枚举: 通过 get_number_of_cameras() 和 get_camera_info() 向框架报告可用 Camera 设备及其静态能力(如分辨率、AE 补偿范围、支持的数据格式等)。
  • 回调注册: set_callbacks() 注册框架回调,用于 HAL 上报错误、Buffer 释放等异步事件。
  • 设备打开: open() 方法创建 camera3_device_t,每个 Camera ID 对应一个设备实例。
注意: 在 HAL3 中,open() 调用会触发 camera3_device_t->ops->initialize(),此时 HAL 应完成所有硬件资源预分配,但 不启动 数据流。

3.3 Camera3Device:设备接口与操作契约

camera3_device_t 代表一个具体的 Camera 硬件设备,其操作函数集 camera3_device_ops_t 定义了 HAL 与框架之间的核心交互契约。

typedef struct camera3_device {
    hw_device_t common;
    camera3_device_ops_t *ops;
    void *priv;  // HAL 私有数据指针
} camera3_device_t;

typedef struct camera3_device_ops {
    int (*initialize)(const struct camera3_device *, 
                      const camera3_callback_ops_t *callback_ops);
    int (*configure_streams)(const struct camera3_device *,
                             camera3_stream_configuration_t *config);
    int (*construct_default_request_settings)(
            const struct camera3_device *, int type);
    int (*process_capture_request)(const struct camera3_device *,
                                   camera3_capture_request_t *request);
    void (*dump)(const struct camera3_device *, int fd);
    int (*flush)(const struct camera3_device *);
    // ... 其他操作
} camera3_device_ops_t;

3.3.1 关键操作流程

  1. initialize():初始化设备,注册框架回调。此时 HAL 应准备好所有内部资源。
  2. configure_streams():配置输出流集合。框架根据应用层需求(预览、拍照、录像)组合多个 camera3_stream_t,HAL 需确认是否支持并分配 Buffer 池。
  3. construct_default_request_settings():为指定模板(如预览、拍照、录像)生成默认的捕获请求设置。
  4. process_capture_request():提交一个捕获请求。这是 HAL3 最核心的异步调用,HAL 必须尽快返回,并在完成后通过回调通知框架。
  5. flush():清空所有待处理的请求,用于快速关闭或异常恢复。
核心原则: process_capture_request() 必须是非阻塞的。HAL 内部应使用工作线程池处理请求,并通过 camera3_callback_ops_t 中的 process_capture_result() 返回结果。

3.4 Pipeline:请求处理流水线

Pipeline 是 HAL3 内部对“从传感器曝光到输出 Buffer 完成”这一完整处理路径的抽象。每个 Camera 设备可以包含多个 Pipeline,每个 Pipeline 对应一个物理摄像头或一个逻辑处理阶段。

Camera HAL3 Pipeline 请求处理流程 应用层 Capture Request Camera Framework 请求分发 & Buffer 管理 HAL3 实现 process_capture_request Sensor / ISP 硬件处理 Pipeline 内部阶段(HAL 实现细节) Sensor 曝光 (曝光时间 + 增益) RAW 域处理 (黑电平 / 去噪) ISP 处理 (AWB / 去马赛克) 后处理 (缩放 / 格式转换) 输出 Buffer 完成 process_capture_result 回调

3.4.1 Pipeline 关键特性

  • 深度流水线: 支持多个请求同时处于不同处理阶段,提高吞吐量。
  • 逐帧参数: 每个请求可以携带独立的 3A 参数、裁剪区域、输出格式等。
  • Buffer 管理: 输入/输出 Buffer 由框架通过 camera3_stream_buffer_t 传递,HAL 负责填充或消费。
实战提示: 在实现 HAL3 时,Pipeline 深度通常设置为 3~6 帧。过浅会导致 CPU 等待,过深会增加延迟。建议根据 Sensor 帧率和 ISP 处理时间动态调整。

3.5 Stream:输出流与配置

camera3_stream_t 是 HAL3 中描述输出 Buffer 规格的核心结构体。一个 Camera 设备可以同时配置多个 Stream,每个 Stream 对应一路独立的输出(如预览 YUV、拍照 JPEG、RAW 数据等)。

typedef struct camera3_stream {
    int stream_type;        // CAMERA3_STREAM_OUTPUT / INPUT / BIDIRECTIONAL
    uint32_t width;
    uint32_t height;
    int format;             // HAL_PIXEL_FORMAT_*
    uint32_t usage;         // GRALLOC_USAGE_*
    uint32_t max_buffers;   // HAL 建议的最大 Buffer 数
    void *priv;             // HAL 私有数据
    android_dataspace_t data_space;
    int rotation;
    // ... 其他字段
} camera3_stream_t;

3.5.1 Stream 配置流程

  1. 框架收集: 应用层通过 CameraDevice.createCaptureSession() 指定输出 Surface 集合。
  2. Stream 组合: 框架将 Surface 转换为 camera3_stream_t 数组,调用 configure_streams()。
  3. HAL 确认: HAL 检查是否支持该组合,并设置 max_buffers、usage 等字段。
  4. Buffer 分配: 框架根据 HAL 返回的配置分配 Gralloc Buffer,并注册到 HAL。

3.5.2 常见 Stream 类型对比

Stream 类型 典型格式 用途 Buffer 方向
OUTPUT YUV420_888 / NV12 / JPEG 预览、拍照、录像 HAL 写入 → 框架消费
INPUT YUV420_888 / RAW10 重处理(Reprocess) 框架写入 → HAL 消费
BIDIRECTIONAL YUV420_888 ZSL(零快门延迟) 双向
Stream 配置约束: 一旦 configure_streams() 成功返回,Stream 集合在 flush() 或 close() 之前不可更改。如果需要动态调整输出规格,必须先停止当前 Session,重新配置。

3.6 请求-响应模型详解

HAL3 的核心数据流模型是 Capture Request → Capture Result。每个请求包含以下关键信息:

typedef struct camera3_capture_request {
    uint32_t frame_number;          // 帧序号,单调递增
    camera3_stream_buffer_t *input_buffers;  // 输入 Buffer(重处理时使用)
    uint32_t num_input_buffers;
    camera3_stream_buffer_t *output_buffers; // 输出 Buffer 列表
    uint32_t num_output_buffers;
    const camera_metadata_t *settings;       // 逐帧 3A 参数
    int32_t *physical_camera_settings;       // 多摄像头时各物理 Camera 参数
    // ...
} camera3_capture_request_t;

3.6.1 请求生命周期

  1. 提交: 框架调用 process_capture_request(),HAL 必须立即返回(非阻塞)。
  2. 处理: HAL 内部将请求加入 Pipeline,Sensor 曝光、ISP 处理、后处理依次执行。
  3. 结果回调: 处理完成后,HAL 通过 process_capture_result() 返回结果元数据(3A 状态、时间戳等)和填充好的 Buffer。
  4. Buffer 释放: 框架消费完 Buffer 后,通过 buffer_release() 回调通知 HAL 可以复用。
关键约束: 结果回调的顺序 不一定 与请求提交顺序一致。HAL 可以乱序返回结果,但必须保证每个 frame_number 唯一且最终都会返回。框架通过 frame_number 关联请求与结果。

3.7 本章小结

  • HAL3 设计理念: 异步流水线、逐帧精细控制、多流并行输出。
  • Camera3Module: 模块入口,负责设备枚举、能力查询和设备打开。
  • Camera3Device: 设备接口,定义 configure_streams()、process_capture_request() 等核心操作。
  • Pipeline: 请求处理流水线,支持多请求并行处理,深度通常为 3~6 帧。
  • Stream: 输出流抽象,支持 OUTPUT、INPUT、BIDIRECTIONAL 三种类型,配置后不可动态修改。
  • 请求-响应模型: 非阻塞提交、异步回调、乱序返回,通过 frame_number 保证一致性。