Camera HAL3 Stream配置与图像格式转换实战 - 第2节
2.1 Stream 核心概念:数据流的抽象
在 Camera HAL3 架构中,Stream 是图像数据流动的抽象载体。它定义了从 Camera 传感器到内存缓冲区的单向数据通道。每个 Stream 都包含一组固定的属性,这些属性在配置阶段确定后,在 Stream 生命周期内不可更改。
关键理解: Stream 不是物理内存,而是描述“谁需要什么格式、多大尺寸、多少帧率”的契约。HAL 根据 Stream 列表分配实际的
buffer_handle_t。
2.1.1 Stream 的核心属性
| 属性 | 类型 | 说明 |
|---|---|---|
stream_type | int | CAMERA3_STREAM_OUTPUT / INPUT / BIDIRECTIONAL |
width | uint32_t | 图像宽度(像素) |
height | uint32_t | 图像高度(像素) |
format | int | HAL_PIXEL_FORMAT_* 枚举值 |
usage | uint32_t | GRALLOC_USAGE_* 标志位组合 |
max_buffers | uint32_t | HAL 建议的缓冲区数量 |
data_space | int | 色彩空间(HAL_DATASPACE_*) |
rotation | int | 输出旋转角度(0/90/180/270) |
实战提示:
usage 标志位决定了 Gralloc 分配内存时的缓存策略。例如 GRALLOC_USAGE_SW_READ_OFTEN 用于 CPU 读取,GRALLOC_USAGE_HW_TEXTURE 用于 GPU 纹理。
2.2 StreamConfiguration:配置集合
StreamConfiguration 是 HAL3 中用于描述一次 Camera 会话(Session)所需所有 Stream 的集合。它由 Framework 通过 configure_streams() 调用传递给 HAL。该结构体包含了操作模式、Stream 数组以及会话参数。
常见陷阱: 不要混淆
StreamConfiguration 与 Camera3StreamConfiguration。前者是 Framework 层的 Java 对象,后者是 HAL 层的 C 结构体。HAL 开发直接操作的是 Camera3StreamConfiguration。
2.2.1 配置流程步骤
- 收集需求: Framework 根据应用层请求(预览、拍照、录像)确定需要的 Stream 列表。
- 构造配置: 填充
Camera3StreamConfiguration,包括num_streams、streams指针数组、operation_mode。 - 调用 HAL: 通过
camera3_device_ops_t.configure_streams()下发配置。 - HAL 验证: HAL 检查每个 Stream 的格式、尺寸、usage 是否支持,返回 0 或负错误码。
- 缓冲区分配: 成功后,Framework 为每个 Stream 分配
max_buffers个 Gralloc 缓冲区。
2.3 Session 参数:操作模式与元数据
Session 参数 是 Camera3StreamConfiguration 中携带的全局配置信息,影响整个 Camera 会话的行为。最重要的两个字段是 operation_mode 和 session_parameters。
2.3.1 operation_mode 枚举值
| 枚举值 | 值 | 典型场景 |
|---|---|---|
CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE | 0 | 标准预览/拍照 |
CAMERA3_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE | 1 | 高速连拍(HFR) |
CAMERA3_STREAM_CONFIGURATION_VENDOR_MODE | 0x8000 | OEM 自定义模式 |
关键点:
session_parameters 是一个 camera_metadata_t 指针,用于传递 Framework 到 HAL 的初始参数,例如 ANDROID_CONTROL_AE_TARGET_FPS_RANGE。HAL 应在此阶段完成传感器初始化。
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_streams | Stream 数量 | 通常为 1~4,超过 4 需确认硬件能力 |
streams | 指向 camera3_stream_t 指针数组 | HAL 可以修改每个 stream 的 max_buffers 和 usage |
operation_mode | 操作模式枚举 | 决定 ISP 管线配置策略 |
session_parameters | 会话级元数据 | HAL 必须解析并应用,不能忽略 |
关键约束: HAL 在
configure_streams() 中不能阻塞超过 200ms。如果需要对传感器重新初始化,必须在此时间内完成。超时会导致 Framework 触发 ANR。
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 开发中最容易出错的环节,务必做好参数校验和日志输出。