4. HAL3 核心数据结构详解

Android Camera HAL3 接口围绕四个核心数据结构构建了完整的相机管道:设备描述、数据流、请求提交与结果返回。理解这些结构是掌握多摄切换与 Pipeline 资源管理的基础。本章逐一拆解其字段含义、生命周期与协作关系。

学习提示:HAL3 的四个核心结构对应着 Camera 框架的“设备-流-请求-结果”四元组。在多摄场景下,每个物理 Camera 设备都拥有一套独立的 camera3_stream_t 集合,而 camera3_capture_request_t 则负责跨设备的同步触发。

4.1 camera3_device_t:HAL 设备句柄

camera3_device_t 是 Camera HAL 设备在框架层的抽象表示,每个逻辑 Camera(包括多摄中的主摄、广角、长焦)都对应一个独立的 camera3_device_t 实例。它由 open() 调用创建,由 close() 销毁。

typedef struct camera3_device {
    // HAL 设备版本号,必须为 HARDWARE_DEVICE_API_VERSION(3, x)
    hw_device_t common;

    // 设备私有数据指针,HAL 实现方使用
    void *priv;

    // 操作函数集:初始化、配置流、提交请求等
    camera3_device_ops_t *ops;

    // 预留字段
    void *reserved[2];
} camera3_device_t;
关键字段说明:
  • common:继承自 hw_device_t,包含 tag、版本号、模块句柄、close 函数指针。框架通过 common.close() 关闭设备。
  • priv:HAL 实现方存放设备上下文(如 Pipeline 管理器指针、传感器驱动句柄)的私有区域。
  • ops:指向 camera3_device_ops_t 结构体,包含 initialize()、configure_streams()、process_capture_request()、flush() 等核心接口。
camera3_device_t 结构关系 camera3_device_t common (hw_device_t) priv (void*) ops (device_ops_t) ops 包含关键函数指针 initialize | configure_streams | process_capture_request | flush

4.2 camera3_stream_t:数据流描述

camera3_stream_t 描述一条从 Camera 传感器到内存缓冲区的数据通道。在多摄场景中,每个物理 Camera 可以同时拥有多个流(预览流、拍照流、视频流),而逻辑 Camera 则通过 camera3_stream_configuration_t 聚合所有物理流的配置。

typedef struct camera3_stream {
    // 流类型:CAMERA3_STREAM_OUTPUT / INPUT / BIDIRECTIONAL
    int stream_type;

    // 图像宽度、高度(像素)
    uint32_t width;
    uint32_t height;

    // 图像格式:HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED / YCbCr_420_888 / BLOB 等
    int format;

    // 使用标记:GRALLOC_USAGE_HW_TEXTURE / GRALLOC_USAGE_HW_CAMERA_WRITE 等
    uint32_t usage;

    // 最大缓冲数(HAL 可修改)
    uint32_t max_buffers;

    // 私有指针:HAL 用于关联 Pipeline 内部状态
    void *priv;

    // 数据空间(颜色空间、动态范围等)
    android_dataspace_t data_space;

    // 旋转角度
    int rotation;

    // 物理 Camera ID(多摄时标识该流属于哪个物理 Camera)
    const char *physical_camera_id;

    // 预留字段
    void *reserved[6];
} camera3_stream_t;
camera3_stream_t 核心字段速查
字段 说明 多摄场景注意事项
stream_type OUTPUT(输出到内存)、INPUT(输入到 ISP)、BIDIRECTIONAL 多摄主输出流通常为 OUTPUT;RAW 流用于第三方算法
format 像素格式,常用 IMPLEMENTATION_DEFINED 让 HAL 自行选择 不同物理 Camera 可能支持不同格式,需在 configure_streams 时协商
max_buffers HAL 请求的缓冲深度,框架会尽量满足 多摄并发时总缓冲数受内存限制,需合理分配
physical_camera_id Android 10+ 引入,标识流所属的物理 Camera 逻辑 Camera 通过此字段将流路由到对应物理 Pipeline
常见陷阱:在多摄切换场景中,physical_camera_id 必须在 configure_streams() 阶段正确设置。如果框架传递的流中 physical_camera_id 为 NULL,HAL 应将其视为逻辑 Camera 的主流。切换时,HAL 需要重新配置流的 physical_camera_id 映射关系,否则会导致数据路由错误。
多摄场景 camera3_stream_t 配置关系 逻辑 Camera camera3_stream_configuration_t(流配置集合) 物理流 1(主摄) physical_camera_id="0" 物理流 2(广角) physical_camera_id="2" 物理流 3(长焦) physical_camera_id="3" 每个物理流独立配置 width/height/format/usage,通过 physical_camera_id 路由到对应 Pipeline 切换时 HAL 需重新配置流集合,更新 physical_camera_id 映射

4.3 camera3_capture_request_t:捕获请求

每次拍照、预览帧或视频帧的采集都由一个 camera3_capture_request_t 发起。它包含了帧号、目标流、控制参数以及物理 Camera 的元数据。在多摄同步场景中,一个请求可以同时包含多个物理 Camera 的设置。

typedef struct camera3_capture_request {
    // 帧号,单调递增,用于追踪请求与结果的对应关系
    uint32_t frame_number;

    // 请求关联的 output stream 指针数组
    const camera3_stream_t *const *output_buffers;

    // output_buffers 数组长度
    uint32_t num_output_buffers;

    // 输入 stream(用于 reprocess 场景)
    const camera3_stream_t *input_buffer;

    // 请求元数据(settings),包含 3A 参数、AE/AWB 模式、裁剪区域等
    const camera_metadata_t *settings;

    // 物理 Camera settings 数组(Android 9+),用于多摄独立控制
    uint32_t num_physcam_settings;
    const camera_metadata_t *const *physcam_settings;

    // 物理 Camera ID 数组,与 physcam_settings 一一对应
    const char *const *physcam_id;

    // 预留字段
    void *reserved[4];
} camera3_capture_request_t;
多摄同步请求关键点:
  • frame_number:全局递增,逻辑 Camera 和物理 Camera 共享同一帧号序列。HAL 必须保证每个 frame_number 对应的结果最终返回。
  • physcam_settings:当逻辑 Camera 包含多个物理 Camera 时,框架通过此数组传递每个物理 Camera 独立的 3A 参数。例如主摄使用中心测光,广角使用平均测光。
  • output_buffers:指向 camera3_stream_buffer_t 数组,每个 buffer 关联一个 stream。多摄场景下,一个请求可能包含来自不同物理 Camera 的多个 output buffer。
camera3_capture_request_t 多摄请求结构 capture_request frame_number=1024 settings (全局) output_buffers[] physcam_settings[] 多摄请求处理流程 1. 框架为每个物理 Camera 准备独立的 physcam_settings 2. HAL 解析 physcam_id 数组,将 settings 路由到对应 Pipeline 3. 所有物理 Camera 使用相同的 frame_number,保证结果同步

4.4 camera3_capture_result_t:捕获结果

HAL 通过 camera3_capture_result_t 将处理后的帧数据、元数据和状态返回给框架。每个 frame_number 对应一个最终结果,但 HAL 可以分多次返回 partial result(例如先返回 metadata,再返回 buffer)。

typedef struct camera3_capture_result {
    // 对应请求的帧号
    uint32_t frame_number;

    // 结果元数据(最终 3A 状态、传感器时间戳、统计信息等)
    const camera_metadata_t *result;

    // 输出 buffer 数组(已填充数据的 buffer)
    uint32_t num_output_buffers;
    const camera3_stream_buffer_t *output_buffers;

    // 输入 buffer(reprocess 场景)
    const camera3_stream_buffer_t *input_buffer;

    // partial result 序号:1 表示第一个 partial,递增到 num_partial_results
    uint32_t partial_result;

    // 物理 Camera 结果元数据(Android 9+)
    uint32_t num_physcam_metadata;
    const camera_metadata_t *const *physcam_metadata;
    const char *const *physcam_ids;

    // 预留字段
    void *reserved[6];
} camera3_capture_result_t;
camera3_capture_result_t 关键字段与多摄场景
字段 作用 多摄场景行为
frame_number 与请求的 frame_number 匹配 所有物理 Camera 的结果共享同一 frame_number,框架据此合并
partial_result 标识 partial result 序号,0 表示最终结果 每个物理 Camera 可以独立返回 partial result,框架按序号合并
physcam_metadata 物理 Camera 的独立元数据 包含每个物理 Camera 的 AE/AWB 状态、镜头位置等,框架用于 UI 显示
output_buffers 填充完成的 buffer 数组 多摄场景下,每个物理 Camera 的 buffer 通过此数组返回,框架根据 stream 的 physical_camera_id 区分
性能关键点:在多摄同步模式下,HAL 必须等待所有物理 Camera 的帧处理完成后才能返回最终结果。如果某个物理 Camera 出现丢帧或延迟,会导致整个逻辑 Camera 的帧率下降。建议在 HAL 实现中为每个物理 Pipeline 设置独立的超时监控,并在超时时返回错误状态而非无限等待。
请求-结果生命周期(多摄同步) 时间 Request N 物理 Cam 0 物理 Cam 1 物理 Cam 2 同步等待 所有物理帧就绪 Result N HAL 必须等待所有物理 Camera 完成帧处理后,组装最终 result 返回框架 partial_result 机制允许先返回 metadata,再返回 buffer,减少预览延迟

4.5 四元组协作流程总结

四个核心数据结构在 Camera HAL3 中的协作遵循以下时序:

  1. 设备初始化:框架调用 open() 获得 camera3_device_t,然后调用 ops->initialize() 传入回调接口。
  2. 流配置:框架构造 camera3_stream_t 数组,通过 ops->configure_streams() 传递给 HAL。HAL 根据 physical_camera_id 分配 Pipeline 资源。
  3. 请求提交:框架填充 camera3_capture_request_t,设置 frame_number、settings、output_buffers 和 physcam_settings,调用 ops->process_capture_request()。
  4. 结果返回:HAL 通过回调函数返回 camera3_capture_result_t,包含处理后的 buffer 和元数据。框架根据 frame_number 匹配请求与结果。
实战建议:在多摄 HAL 实现中,建议为每个 camera3_device_t 维护一个帧号到请求上下文的映射表。当收到 process_capture_request 时,将请求拆分为多个物理 Pipeline 子请求,并记录每个子请求的完成状态。只有当所有物理子请求都完成时,才组装最终结果并回调框架。这样可以保证多摄同步的时序正确性。