4、Stream 配置数据结构:camera3_stream_t 与 camera3_stream_configuration_t 详解

在 Camera HAL3 多路 Stream 并行捕获中,camera3_stream_t 和 camera3_stream_configuration_t 是连接 Framework 与 HAL 的核心数据结构。Framework 通过 configure_streams() 调用将配置下发,HAL 据此分配硬件管道、ISP 带宽和内存缓冲区。理解这两个结构体的每个字段,是正确实现多路并行捕获的前提。

关键认知: camera3_stream_configuration_t 描述“一组 Stream 的集合”,而 camera3_stream_t 描述“单个 Stream 的属性”。HAL 必须根据集合中的约束(如操作模式、Stream 数量)来验证每个 Stream 的参数是否合法。

4.1 camera3_stream_t:单个 Stream 的属性定义

每个 Stream 代表一条从 Sensor 到内存的数据通路。其结构体定义如下:

typedef struct camera3_stream {
    uint32_t      stream_type;       // CAMERA3_STREAM_OUTPUT / INPUT / BIDIRECTIONAL
    uint32_t      width;             // 图像宽度(像素)
    uint32_t      height;            // 图像高度(像素)
    int32_t       format;            // 像素格式(如 HAL_PIXEL_FORMAT_YCbCr_420_888)
    uint32_t      rotation;          // 旋转角度(0 / 90 / 180 / 270)
    int32_t       usage;             // 缓冲区使用标志(GRALLOC_USAGE_*)
    uint32_t      max_buffers;       // HAL 请求的最大缓冲区数
    void         *priv;              // HAL 私有数据指针
    uint32_t      data_space;        // 色彩空间(HAL_DATASPACE_*)
    int32_t       rotation_override; // 旋转覆盖(Android 12+)
    uint32_t     *physical_camera_id;// 物理 Camera ID 数组(多摄)
    int32_t       num_physical_cameras;// 物理 Camera 数量
    int32_t       timestamp_source;  // 时间戳来源(TANSPARENT / REALTIME)
} camera3_stream_t;
字段详解:
  • stream_type:决定数据流向。OUTPUT 用于预览/拍照/录像;INPUT 用于 reprocess(如美颜);BIDIRECTIONAL 用于 YUV 回写。
  • format:多路并行时,不同 Stream 可使用不同格式。例如预览用 YCbCr_420_888,拍照用 JPEG。
  • usage:影响 Gralloc 分配策略。VIDEO_ENCODER 需连续内存,SW_READ_OFTEN 需 CPU 可访问。
  • max_buffers:HAL 通过此字段告知 Framework 需要多少个 buffer 才能保持流水线不空转。多路并行时,每个 Stream 的 max_buffers 之和受限于 ISP 带宽。
  • priv:HAL 内部使用,Framework 不修改。可用于存储 Stream 对应的硬件管道 ID。

4.2 camera3_stream_configuration_t:Stream 集合与操作模式

该结构体将多个 Stream 打包,并携带全局配置参数:

typedef struct camera3_stream_configuration {
    uint32_t              num_streams;          // Stream 数量
    camera3_stream_t    **streams;              // Stream 指针数组
    uint32_t              operation_mode;       // CAMERA3_STREAM_CONFIGURATION_*
    const camera_metadata_t *session_parameters;// 会话级参数(如 HDR 模式)
    uint32_t              stream_config_counter;// 配置计数器(用于去重)
} camera3_stream_configuration_t;
常见陷阱: 多路并行时,num_streams 可能达到 4~6 个(预览 + 拍照 + 录像 + 深度 + 回调)。HAL 必须检查所有 Stream 的 width/height/format 组合是否在 ISP 能力范围内。如果某个 Stream 的 max_buffers 设置过大,可能导致其他 Stream 无法分配足够 buffer。

4.3 多路并行配置的约束关系

下表总结了多路 Stream 并行时各字段的典型约束:

字段 单路场景 多路并行场景 常见错误
stream_type OUTPUT 可混合 OUTPUT + INPUT BIDIRECTIONAL 用于非 reprocess 流
format YUV 或 JPEG 不同 Stream 可不同格式 JPEG 流与 YUV 流分辨率不匹配
width/height 固定分辨率 各 Stream 分辨率可不同,但需满足 ISP 缩放比 预览 1920x1080 + 拍照 4000x3000 超出 ISP 最大输入
usage GRALLOC_USAGE_HW_TEXTURE 需根据用途组合(VIDEO_ENCODER + SW_READ_OFTEN) 所有 Stream 使用相同 usage 导致内存浪费
max_buffers 3~4 总和受限于 ISP 带宽,通常 ≤ 12 单个 Stream 设置 8 导致其他 Stream 无 buffer
operation_mode NORMAL CONSTRAINED_HIGH_SPEED 用于高速连拍 多路并行时误用 NORMAL 导致帧率下降

4.4 多路 Stream 配置流程图

以下 SVG 展示了 Framework 下发配置后,HAL 内部对 camera3_stream_configuration_t 的解析与验证流程:

多路 Stream 配置解析与验证流程 Framework 下发 configure_streams() 解析 operation_mode 遍历 num_streams 验证每个 Stream 检查 format / width / height / usage 是否在 ISP 能力列表内? 分配 max_buffers 并返回 注意点 多路并行时, max_buffers 总和 不能超过 ISP 带宽

4.5 多路并行配置实战要点

  1. Stream 数量上限:通常 HAL 支持 4~6 个并行 Stream。超过时需降级或拒绝配置。
  2. 分辨率组合:所有 Stream 的宽高必须 ≤ Sensor 最大输出分辨率。例如 48MP Sensor 不能同时输出 48MP 预览 + 48MP 拍照。
  3. 格式兼容性:JPEG 流通常需要额外的 YUV 中间流,HAL 需在内部创建隐藏 Stream。
  4. max_buffers 计算:建议按“帧率 × 流水线深度”估算。30fps 预览 + 30fps 录像,每个 Stream 至少 4 个 buffer。
  5. operation_mode 选择:多路并行时优先使用 CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED 以获取更高帧率。
实战案例: 某设备需要同时输出 1080p 预览(YUV)、4K 录像(YUV)和 12MP 拍照(JPEG)。HAL 在 configure_streams() 中应:
  • 检查 1080p + 4K 是否在 ISP 缩放范围内;
  • 为 JPEG 流内部创建 12MP YUV 中间流;
  • 设置预览 max_buffers=4,录像 max_buffers=6,拍照 max_buffers=2;
  • 返回时在 stream->max_buffers 中填入实际值。

4.6 数据结构关系图

以下 SVG 展示了 camera3_stream_configuration_t 与 camera3_stream_t 之间的层级关系:

camera3_stream_configuration_t 与 camera3_stream_t 关系 camera3_stream_configuration_t num_streams = 3 operation_mode = NORMAL streams → [ptr0, ptr1, ptr2] Stream 0 (预览) width=1920 height=1080 format=YUV max_buffers=4 usage=TEXTURE Stream 1 (录像) width=3840 height=2160 format=YUV max_buffers=6 usage=ENCODER Stream 2 (拍照) width=4000 height=3000 format=JPEG max_buffers=2 usage=SW_READ

4.7 常见问题与避坑指南

问题 原因 解决方案
configure_streams 返回 BAD_VALUE Stream 格式或分辨率不在 HAL 支持列表中 在 getCameraCharacteristics() 中正确上报 SCALER_AVAILABLE_STREAM_CONFIGURATIONS
预览卡顿,录像丢帧 max_buffers 设置过小,导致 dequeue 等待 增大 max_buffers,或降低帧率要求
拍照 JPEG 花屏 JPEG 流缺少对应的 YUV 中间流 HAL 内部创建隐藏 YUV Stream 用于 JPEG 编码
多路 Stream 帧率不一致 ISP 带宽分配不均,或某个 Stream 占用过多 buffer 使用 session_parameters 设置带宽分配策略
调试建议: 在 HAL 的 configure_streams() 实现中,打印所有 Stream 的 width/height/format/max_buffers 到 log。对比 Framework 下发的值与实际 ISP 能力,可以快速定位配置不匹配问题。