4. HAL3 Pipeline 模型:request、result、stream、buffer 管理、pipeline 深度解析

Camera HAL3 的核心设计思想是 Pipeline(流水线) 模型。它将一次拍照或预览抽象为一个由多个阶段组成的、可并行处理的请求-响应循环。理解 Pipeline 模型是掌握 HAL3 适配的关键,它直接决定了相机的吞吐量、延迟和资源利用率。

核心要点: HAL3 Pipeline 是一个基于 异步请求 的框架。应用层下发 capture request,HAL 层处理并返回 capture result,整个过程通过 Stream(流) 和 Buffer(缓冲区) 进行数据传递。

4.1 Pipeline 核心概念与数据流

Pipeline 模型包含四个核心抽象:Request、Result、Stream 和 Buffer。它们之间的关系构成了 HAL3 的数据流动骨架。

HAL3 Pipeline 核心数据流模型 App / Framework Request HAL Pipeline Result App / Framework Stream (流) 定义图像格式、分辨率、 使用场景 (Preview/Video/Still) Buffer (缓冲区) 实际图像数据载体, 通过 Dequeue/Enqueue 流转 Pipeline 核心原则 1. 每个 Request 对应一个 Result,形成闭环。 2. Stream 是 Buffer 的逻辑容器,Buffer 是 Stream 的物理实例。

4.2 Request 与 Result:请求-响应契约

Capture Request 是 Pipeline 的输入,Capture Result 是输出。它们通过 frame_number 唯一关联,形成一对一的契约关系。

4.2.1 Capture Request 结构

一个 Request 包含以下关键字段:

字段 类型 说明
frame_number uint32_t 帧序号,唯一标识一次捕获请求
settings metadata 3A 参数、AE/AF/AWB 模式、效果、裁剪区域等
input_buffers buffer_handle_t* 输入缓冲区(用于 reprocessing 场景)
output_buffers buffer_handle_t* 输出缓冲区列表,每个 buffer 关联一个 stream
适配提示: 在 Treble 架构下,Request 通过 HIDL 接口从 CameraService 下发到 HAL。HAL 实现必须保证 process_capture_request 是线程安全的,因为多个 Request 可能同时到达。

4.2.2 Capture Result 结构

Result 是 HAL 对 Request 的响应,包含处理后的元数据和填充好的缓冲区:

// HAL3 中 Result 的核心结构
typedef struct camera3_capture_result {
    uint32_t            frame_number;       // 对应 Request 的帧号
    const camera3_stream_buffer_t *output_buffers; // 输出缓冲区数组
    uint32_t            num_output_buffers; // 输出缓冲区数量
    const camera3_stream_buffer_t *input_buffers;  // 输入缓冲区(reprocessing)
    uint32_t            num_input_buffers;
    const camera_metadata_t *result;        // 最终元数据(包含 3A 结果、统计信息等)
    uint32_t            partial_result;     // 部分结果标记(用于分阶段返回)
} camera3_capture_result_t;

4.3 Stream 与 Buffer 管理

Stream 定义了数据的格式和用途,Buffer 是实际的数据载体。HAL3 通过 configure_streams 建立 Stream 配置,然后在运行时通过 Buffer 管理机制进行数据交换。

4.3.1 Stream 配置表

Stream 类型 典型用途 格式示例 Buffer 数量
CAMERA3_STREAM_OUTPUT 预览、视频、拍照 YUV_420_888, JPEG, HEIC 3~8
CAMERA3_STREAM_INPUT Reprocessing(如美颜、HDR) YUV_420_888 2~4
CAMERA3_STREAM_BIDIRECTIONAL ZSL(零快门延迟) YUV_420_888 4~6

4.3.2 Buffer 管理流程

Buffer 在 HAL 和 Framework 之间通过 Dequeue → Fill → Enqueue 循环流转:

  1. Dequeue: HAL 从 Stream 的 Buffer 池中取出一个空闲 Buffer。
  2. Fill: HAL 将 Sensor 数据或 ISP 处理后的数据写入 Buffer。
  3. Enqueue: HAL 将填充好的 Buffer 通过 process_capture_result 返回给 Framework。
  4. Release: Framework 消费完数据后,将 Buffer 归还给 HAL 的 Buffer 池。
Buffer 生命周期管理流程 Buffer Pool Dequeue Fill (HAL) Enqueue Release (Framework 消费后归还) Buffer 管理关键点 • 避免 Buffer 泄漏:每个 Dequeue 必须对应一个 Enqueue 或 Release。 • 使用 camera3_stream_buffer_lock 机制防止并发访问冲突。

4.4 Pipeline 深度解析:从 Request 到 Result 的完整路径

一个完整的 Pipeline 周期包含以下阶段:

阶段 负责方 关键操作 延迟瓶颈
1. Request 构建 Framework 填充 metadata,关联 output_buffers 应用层逻辑
2. Request 下发 CameraService 通过 HIDL 调用 process_capture_request IPC 延迟
3. Sensor 曝光 HAL 配置 sensor 参数,触发曝光 曝光时间 (通常 10~33ms)
4. ISP 处理 HAL RAW→YUV/JPEG 转换,3A 统计 ISP 时钟频率、算法复杂度
5. Buffer 填充 HAL 将处理后的数据写入 output_buffers 内存带宽
6. Result 返回 HAL 调用 process_capture_result 回调 IPC 延迟
常见适配陷阱: 在 Treble 架构下,HAL 实现必须注意 Pipeline 深度(即同时处理的 Request 数量)。深度过小会导致 CPU 空闲等待,深度过大会增加内存压力和延迟。建议根据 Sensor 帧率和 ISP 处理时间动态调整 Pipeline 深度,通常保持在 2~4 之间。

4.5 Pipeline 深度与性能调优

Pipeline 深度(outstanding request count)是 HAL3 性能调优的核心参数。它决定了系统能够同时处理多少个未完成的 Request。

Pipeline 深度对吞吐量的影响 Pipeline 深度 = 1 串行处理,CPU 空闲等待 吞吐量低,延迟稳定 Pipeline 深度 = 4 并行处理,流水线满载 吞吐量高,延迟适中 Pipeline 深度 = 8 过度并行,内存压力大 延迟增加,可能丢帧 深度调优建议 • 对于 30fps 预览:深度 2~3 即可满足需求。 • 对于高速连拍 (60fps+):深度建议 4~6,同时增加 Buffer 池大小。 • 使用 ANDROID_REQUEST_PIPELINE_DEPTH 元数据向 Framework 报告当前深度。

4.6 Treble 架构下的 Pipeline 适配要点

在 Treble 架构中,HAL3 Pipeline 的实现需要额外关注以下方面:

  • HIDL 接口封装: process_capture_request 和 process_capture_result 需要通过 ICameraDevice HIDL 接口进行跨进程调用,注意 IPC 性能开销。
  • Buffer 传递: 使用 hidl_memory 或 native_handle_t 传递 Buffer 句柄,避免跨进程拷贝大块数据。
  • 同步机制: 利用 camera3_stream_buffer 中的 acquire_fence 和 release_fence 实现跨进程同步,防止数据竞争。
  • Vendor 扩展: 在 Pipeline 中插入 Vendor 特定的处理节点(如 AI 降噪、HDR 融合)时,必须通过 vendor_tag 暴露配置接口。
最佳实践: 在 Treble HAL 实现中,建议将 Pipeline 的核心逻辑(Sensor 控制、ISP 处理)放在 Vendor 分区,而将 Buffer 管理和 IPC 通信放在 Framework 分区。这样既能保证性能,又能满足 Treble 的模块化要求。