2. HAL3核心数据结构:camera3_device_t、camera3_callback_ops_t、camera3_stream_t 结构体详解

在 HAL3 架构中,Camera 设备的行为完全由三个核心数据结构驱动:设备描述符、回调接口和流配置。它们是 Framework 与 HAL 之间通信的契约基础,也是移植工作中必须精确实现的接口层。本章将逐一拆解这三个结构体的字段含义、生命周期和典型实现模式。

2.1 camera3_device_t:HAL 设备的“身份证”

camera3_device_t 是 Framework 视角下单个 Camera 设备的抽象。它继承自 hw_device_t,并扩展了 HAL3 特有的操作函数表。Framework 通过该结构体调用 open、initialize、configure_streams、process_capture_request 等核心方法。

字段 类型 说明
common hw_device_t HAL 通用设备头,包含 tag、version、module、close 等基础字段
ops camera3_device_ops_t * 设备操作函数表指针,是 HAL 实现的核心入口
priv void * HAL 私有数据指针,通常指向设备上下文结构体
移植要点:priv 字段是 HAL 实现的关键——它允许你在 open 时分配一个包含相机传感器信息、流状态、请求队列等数据的上下文结构体,并在后续所有 ops 回调中通过 reinterpret_cast<YourDeviceContext*>(device->priv) 访问。

以下是一个典型的设备上下文结构体定义示例:

struct CameraDeviceContext {
    int camera_id;
    camera_metadata_t *static_metadata;
    camera_metadata_t *default_request_settings[CAMERA3_TEMPLATE_COUNT];
    // 流管理
    std::vector<camera3_stream_t*> configured_streams;
    // 请求队列
    std::queue<camera3_capture_request_t*> pending_requests;
    // 回调接口
    const camera3_callback_ops_t *callback_ops;
    // 硬件抽象层句柄
    void *sensor_hw_handle;
};

2.2 camera3_callback_ops_t:从 HAL 到 Framework 的“回音壁”

camera3_callback_ops_t 是 Framework 注册给 HAL 的回调函数表。HAL 在完成帧捕获、错误处理、缓冲区释放等事件时,通过该结构体中的函数指针通知 Framework。它定义了三个核心回调:

  • process_capture_result:返回捕获结果,包括 metadata 和输出缓冲区。
  • notify:发送异步事件通知,如快门事件、错误事件。
  • flush:Framework 请求 HAL 立即完成或取消所有待处理请求。
实现建议:在 initialize() 调用中,Framework 会将 camera3_callback_ops_t 指针传入 HAL。HAL 必须保存该指针,并在后续所有回调中使用。建议在设备上下文结构体中用 const camera3_callback_ops_t *callback_ops 字段保存,并在每次回调前做空指针检查。

回调函数的典型调用场景如下:

// 在 HAL 的某个工作线程中,完成一帧捕获后:
void on_capture_completed(CameraDeviceContext *ctx,
                          uint32_t frame_number,
                          camera_metadata_t *result_metadata,
                          const camera3_stream_buffer_t *output_buffers,
                          uint32_t num_output_buffers) {
    camera3_capture_result_t result = {};
    result.frame_number = frame_number;
    result.result = result_metadata;
    result.num_output_buffers = num_output_buffers;
    result.output_buffers = output_buffers;
    result.partial_result = 0;  // 非分片结果

    ctx->callback_ops->process_capture_result(ctx->callback_ops, &result);
}
HAL3 核心数据结构关系图 Framework camera3_device_t camera3_callback_ops_t camera3_stream_t HAL 实现层 说明: Framework 通过 camera3_device_t.ops 调用 HAL;HAL 通过 camera3_callback_ops_t 回调 Framework; camera3_stream_t 在 configure_streams 中由 Framework 传入,HAL 填充其私有字段。

2.3 camera3_stream_t:数据流的“管道契约”

camera3_stream_t 描述了一条从 Camera 传感器到输出目标(如 Surface、编码器)的数据流。它在 configure_streams() 调用中由 Framework 传入数组,HAL 需要验证并填充每个流的格式、分辨率、usage 等字段。

字段 方向 说明
stream_type Framework→HAL CAMERA3_STREAM_OUTPUT / INPUT / BIDIRECTIONAL
width, height Framework→HAL 图像分辨率,HAL 可调整到硬件支持的最接近值
format Framework→HAL 像素格式,如 HAL_PIXEL_FORMAT_YCbCr_420_888
usage Framework→HAL 缓冲区使用标志,如 GRALLOC_USAGE_HW_TEXTURE
max_buffers HAL→Framework HAL 请求的最大缓冲区数量
priv HAL 私有 HAL 可附加私有数据,如关联的 Gralloc 缓冲区句柄
data_space Framework→HAL 色彩空间和动态范围信息
rotation Framework→HAL 输出旋转角度(0/90/180/270)
常见陷阱:在 configure_streams() 中,HAL 必须检查 stream_type 和 format 组合是否被硬件支持。如果某个流无法满足,应返回 -EINVAL 并在 stream 的 priv 中设置错误原因。另外,max_buffers 的设定直接影响内存占用和延迟,建议根据硬件 pipeline 深度合理设置(通常 3~6 个)。

2.4 三者的协作流程

在 HAL3 的完整生命周期中,这三个结构体按照以下顺序协作:

  1. 设备打开:Framework 调用 open(),HAL 分配 camera3_device_t 并填充 ops 和 priv。
  2. 初始化:Framework 调用 initialize(),传入 camera3_callback_ops_t 指针,HAL 保存该指针。
  3. 流配置:Framework 调用 configure_streams(),传入 camera3_stream_t 数组,HAL 验证并调整参数。
  4. 请求处理:Framework 调用 process_capture_request(),HAL 处理请求并通过 camera3_callback_ops_t 返回结果。
  5. 设备关闭:Framework 调用 close(),HAL 释放所有资源。
camera3_device_t / callback_ops_t / stream_t 协作流程 1. open() 2. initialize() 3. configure_streams() 4. process_capture_request() 循环处理请求直到 flush() 或 close() 5. close() 各步骤涉及的核心数据结构: • open() → 分配 camera3_device_t,填充 ops 和 priv • initialize() → 接收并保存 camera3_callback_ops_t 指针 • configure_streams() → 接收 camera3_stream_t 数组,验证并填充 max_buffers 等字段 • process_capture_request() → 通过 callback_ops 返回结果

2.5 移植实战中的常见问题

案例:某平台在移植时发现预览画面卡顿,经排查发现 configure_streams() 中 HAL 将 max_buffers 设置为 1,导致 Framework 每次只能提交一个请求,Pipeline 无法并行。修复方案:根据硬件 ISP 的 pipeline 深度(该平台为 4 级),将 max_buffers 调整为 4,卡顿问题解决。

以下是移植过程中需要重点检查的 checklist:

  • camera3_device_t.ops:确保所有函数指针非空,特别是 configure_streams、process_capture_request、flush。
  • camera3_callback_ops_t:在 initialize() 中保存后,每次回调前检查指针有效性。
  • camera3_stream_t:在 configure_streams() 中检查 stream_type 和 format 组合,确保 max_buffers 不小于 2。
  • 内存管理:priv 指针指向的内存必须在 close() 中正确释放,避免内存泄漏。

掌握这三个核心结构体,就掌握了 HAL3 移植的“骨架”。下一层我们将深入 camera3_device_ops_t 中的每一个操作函数,理解它们的具体实现要求。