Camera HAL3 Stream配置与图像格式转换实战 - 第2节

2.1 Stream 核心概念:数据流的抽象

在 Camera HAL3 架构中,Stream 是图像数据流动的抽象载体。它定义了从 Camera 传感器到内存缓冲区的单向数据通道。每个 Stream 都包含一组固定的属性,这些属性在配置阶段确定后,在 Stream 生命周期内不可更改。

关键理解: Stream 不是物理内存,而是描述“谁需要什么格式、多大尺寸、多少帧率”的契约。HAL 根据 Stream 列表分配实际的 buffer_handle_t。

2.1.1 Stream 的核心属性

属性类型说明
stream_typeintCAMERA3_STREAM_OUTPUT / INPUT / BIDIRECTIONAL
widthuint32_t图像宽度(像素)
heightuint32_t图像高度(像素)
formatintHAL_PIXEL_FORMAT_* 枚举值
usageuint32_tGRALLOC_USAGE_* 标志位组合
max_buffersuint32_tHAL 建议的缓冲区数量
data_spaceint色彩空间(HAL_DATASPACE_*)
rotationint输出旋转角度(0/90/180/270)
实战提示: usage 标志位决定了 Gralloc 分配内存时的缓存策略。例如 GRALLOC_USAGE_SW_READ_OFTEN 用于 CPU 读取,GRALLOC_USAGE_HW_TEXTURE 用于 GPU 纹理。
Stream 属性结构图 CameraStream stream_type width / height format usage max_buffers data_space rotation

2.2 StreamConfiguration:配置集合

StreamConfiguration 是 HAL3 中用于描述一次 Camera 会话(Session)所需所有 Stream 的集合。它由 Framework 通过 configure_streams() 调用传递给 HAL。该结构体包含了操作模式、Stream 数组以及会话参数。

常见陷阱: 不要混淆 StreamConfiguration 与 Camera3StreamConfiguration。前者是 Framework 层的 Java 对象,后者是 HAL 层的 C 结构体。HAL 开发直接操作的是 Camera3StreamConfiguration。

2.2.1 配置流程步骤

  1. 收集需求: Framework 根据应用层请求(预览、拍照、录像)确定需要的 Stream 列表。
  2. 构造配置: 填充 Camera3StreamConfiguration,包括 num_streams、streams 指针数组、operation_mode。
  3. 调用 HAL: 通过 camera3_device_ops_t.configure_streams() 下发配置。
  4. HAL 验证: HAL 检查每个 Stream 的格式、尺寸、usage 是否支持,返回 0 或负错误码。
  5. 缓冲区分配: 成功后,Framework 为每个 Stream 分配 max_buffers 个 Gralloc 缓冲区。
StreamConfiguration 配置流程 Framework 收集需求 构造配置集合 调用 configure_streams HAL 验证 分配 Gralloc 缓冲区

2.3 Session 参数:操作模式与元数据

Session 参数 是 Camera3StreamConfiguration 中携带的全局配置信息,影响整个 Camera 会话的行为。最重要的两个字段是 operation_mode 和 session_parameters。

2.3.1 operation_mode 枚举值

枚举值值典型场景
CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE0标准预览/拍照
CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE1高速连拍(HFR)
CAMERA3_STREAM_CONFIGURATION_VENDOR_MODE0x8000OEM 自定义模式
关键点: session_parameters 是一个 camera_metadata_t 指针,用于传递 Framework 到 HAL 的初始参数,例如 ANDROID_CONTROL_AE_TARGET_FPS_RANGE。HAL 应在此阶段完成传感器初始化。
Session 参数结构 operation_mode session_parameters 影响整个 Camera 会话的行为

2.4 Camera3StreamConfig 结构体深度解析

Camera3StreamConfiguration 是 HAL3 中定义在 camera3.h 的核心结构体。它作为 configure_streams() 的输入参数,承载了所有 Stream 配置信息。

2.4.1 结构体定义

typedef struct camera3_stream_configuration {
    uint32_t                    num_streams;
    camera3_stream_t            **streams;
    uint32_t                    operation_mode;
    const camera_metadata_t     *session_parameters;
} camera3_stream_configuration_t;

2.4.2 字段详解

字段说明HAL 开发注意事项
num_streamsStream 数量通常为 1~4,超过 4 需确认硬件能力
streams指向 camera3_stream_t 指针数组HAL 可以修改每个 stream 的 max_buffers 和 usage
operation_mode操作模式枚举决定 ISP 管线配置策略
session_parameters会话级元数据HAL 必须解析并应用,不能忽略
关键约束: HAL 在 configure_streams() 中不能阻塞超过 200ms。如果需要对传感器重新初始化,必须在此时间内完成。超时会导致 Framework 触发 ANR。
Camera3StreamConfiguration 结构体 camera3_stream_configuration_t configure_streams() 输入参数 num_streams streams[] operation_mode session_parameters HAL 可修改 streams[i]->max_buffers 和 usage,但不能修改 format/width/height

2.5 实战:Stream 配置的典型场景

以下是一个典型的双 Stream 配置(预览 + 拍照)的代码片段,展示如何填充 Camera3StreamConfiguration。

// 假设已有两个 camera3_stream_t 对象:preview_stream 和 capture_stream
camera3_stream_configuration_t stream_config;
memset(&stream_config, 0, sizeof(stream_config));

stream_config.num_streams = 2;
camera3_stream_t *streams[2] = {&preview_stream, &capture_stream};
stream_config.streams = streams;
stream_config.operation_mode = CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE;

// session_parameters 由 Framework 传入,HAL 直接使用
stream_config.session_parameters = request_metadata;

// 调用 HAL 的 configure_streams
int ret = device->ops->configure_streams(device, &stream_config);
if (ret != 0) {
    // 错误处理:格式不支持、尺寸超限等
    ALOGE("configure_streams failed: %d", ret);
}
调试技巧: 在 configure_streams() 入口打印所有 Stream 的 format、width、height,使用 ALOGD 输出到 logcat。这是排查“黑屏/花屏”问题的第一步。

2.6 本章小结

  • Stream 是图像数据通道的抽象,包含 format、size、usage 等不可变属性。
  • StreamConfiguration 是 Stream 的集合,通过 configure_streams() 传递给 HAL。
  • Session 参数 包括 operation_mode 和 session_parameters,影响整个会话行为。
  • Camera3StreamConfiguration 是 HAL 层直接操作的结构体,HAL 可以修改 max_buffers 和 usage。
  • 配置阶段是 HAL 开发中最容易出错的环节,务必做好参数校验和日志输出。