3. HAL3 关键数据结构:定义、作用与性能影响
Camera HAL3 架构的核心交互围绕一组精确定义的数据结构展开。这些结构不仅是 Framework 与 HAL 之间的通信契约,更是性能优化与 CTS 测试验证的直接操作对象。理解它们的布局、生命周期与约束,是进行 pipeline 调优和问题定位的基础。
3.1 数据结构全景图
下图展示了 HAL3 中四个核心数据结构在 Capture Request 生命周期中的流转关系:
3.2 StreamConfiguration:数据流拓扑定义
StreamConfiguration 是 HAL3 初始化阶段最重要的结构体,它定义了 Camera 设备所有数据流的整体拓扑。Framework 在 configure_streams() 调用中传入该结构,HAL 据此分配内部资源。
核心字段与作用:
- streams:
camera3_stream_t*数组,包含所有待配置的 Stream 指针。 - operation_mode:
uint32_t,指定操作模式(如 NORMAL、CONSTRAINED_HIGH_SPEED)。 - num_streams:
uint32_t,streams 数组的长度。
| 字段 | 类型 | 说明 | 性能影响 |
|---|---|---|---|
streams |
camera3_stream_t** |
指向所有 Stream 的指针数组 | Stream 数量与排列顺序影响 HAL 的 pipeline 调度策略 |
operation_mode |
uint32_t |
NORMAL / CONSTRAINED_HIGH_SPEED 等 | 高速模式需额外预留 ISP 带宽,影响帧率上限 |
num_streams |
uint32_t |
Stream 总数 | 过多 Stream 会竞争硬件资源,导致延迟增加 |
CTS 验证要点:CTS 会测试多种 operation_mode 组合,确保 HAL 在切换模式时不会出现资源泄漏或帧率骤降。性能优化中应关注 configure_streams() 的调用耗时,通常应控制在 50ms 以内。
3.3 Stream:单条数据通道的抽象
camera3_stream_t 描述一条独立的数据流通道。每个 Stream 对应一个特定的图像消费者(如 Preview Surface、Video Codec、ImageReader)。
typedef struct camera3_stream {
int stream_type; // CAMERA3_STREAM_OUTPUT / INPUT / BIDIRECTIONAL
uint32_t width; // 图像宽度(像素)
uint32_t height; // 图像高度(像素)
int format; // 像素格式(HAL_PIXEL_FORMAT_*)
uint32_t usage; // 图形缓冲区使用标志(GRALLOC_USAGE_*)
uint32_t max_buffers; // HAL 请求的最大 buffer 数
void *priv; // HAL 私有数据指针
uint32_t rotation; // 旋转角度(0/90/180/270)
int data_space; // 色彩空间(HAL_DATASPACE_*)
} camera3_stream_t;
| 字段 | 关键值示例 | 性能优化关注点 |
|---|---|---|
stream_type |
OUTPUT / INPUT | INPUT 流(如 ZSL)需额外内存拷贝路径 |
width × height |
1920×1080, 640×480 | 分辨率越高,ISP 处理时间与带宽占用越大 |
format |
YCbCr_420_888, RAW10 | RAW 格式需额外 demosaic 处理;YUV 格式兼容性最好 |
usage |
GRALLOC_USAGE_HW_TEXTURE | 错误 usage 会导致 GPU/Display 额外格式转换 |
max_buffers |
3 ~ 8 | 值过小导致 dequeue 阻塞;过大增加内存压力 |
常见陷阱:部分 HAL 实现会忽略 rotation 字段,导致预览方向错误。CTS 测试会验证所有旋转角度下的输出正确性。性能优化时,应避免在 HAL 层做旋转操作,交由显示合成器处理。
3.4 CameraMetadata:控制与结果元数据
CameraMetadata 是 HAL3 中传递控制参数和结果信息的核心容器。它使用键值对(tag-value)方式存储,支持静态、动态、控制三类元数据。
性能优化关键元数据 Tag:
ANDROID_SENSOR_FRAME_DURATION:控制帧间隔,直接影响帧率上限。ANDROID_CONTROL_AE_TARGET_FPS_RANGE:AE 目标帧率范围,影响曝光策略。ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES:热像素校正模式,开启后增加 ISP 负载。ANDROID_TONEMAP_MODE:色调映射模式,FAST 模式可减少 GPU 后处理。
3.5 Buffer:图像数据的内存载体
camera3_stream_buffer_t 是实际图像数据的内存描述结构。它通过 Gralloc 分配图形缓冲区,在 HAL 与消费者之间传递。
typedef struct camera3_stream_buffer {
camera3_stream_t *stream; // 所属 Stream
buffer_handle_t *buffer; // Gralloc buffer 句柄
int status; // CAMERA3_BUFFER_STATUS_OK / ERROR
int acquire_fence; // 获取同步 fence fd
int release_fence; // 释放同步 fence fd
} camera3_stream_buffer_t;
| 字段 | 作用 | 性能优化要点 |
|---|---|---|
buffer |
指向实际图像内存的句柄 | 使用 GRALLOC_USAGE_HW_VIDEO_ENCODER 可避免编码前额外拷贝 |
acquire_fence |
HAL 等待 buffer 可用的同步信号 | fence 等待时间过长会导致 pipeline 空转 |
release_fence |
HAL 通知消费者 buffer 已填充完成 | 延迟释放 fence 会阻塞 dequeue 操作 |
status |
标记 buffer 是否有效 | ERROR 状态需立即丢弃,避免显示花屏 |
Buffer 管理最佳实践:
- 合理设置
max_buffers:预览流通常 3~4 个,视频流 4~6 个,RAW 流 2~3 个。 - 使用
acquire_fence实现异步等待,避免 CPU 轮询。 - 在 HAL 层实现 buffer 池复用,减少 Gralloc 分配/释放开销。
3.6 数据结构间的协同与性能约束
四个数据结构并非独立存在,它们之间的协同关系直接影响整体性能:
- StreamConfiguration → Stream:配置阶段决定了 Stream 的数量与属性,后续无法动态增减。
- Stream → Buffer:每个 Stream 关联一个 buffer 队列,队列深度由
max_buffers控制。 - CameraMetadata → Buffer:每帧的 control 元数据决定 ISP 如何处理 buffer 中的原始数据。
- Buffer → CameraMetadata:HAL 在填充 buffer 后,将动态元数据(如 timestamp、AE 状态)附加到 result 中。
CTS 测试高频失败点:
configure_streams()返回后,Stream 的max_buffers值被 HAL 修改,但 Framework 未预期到该变化。- CameraMetadata 中缺少强制 Tag(如
ANDROID_SENSOR_TIMESTAMP),导致 CTS 测试项失败。 - Buffer 的
release_fence未正确关闭,造成文件描述符泄漏。
3.7 小结:数据结构与性能优化的映射关系
| 数据结构 | 性能优化切入点 | CTS 验证项示例 |
|---|---|---|
| StreamConfiguration | 减少不必要的 Stream 数量;优化 operation_mode 切换延迟 | TestConfigureStreams |
| Stream | 选择合适的分辨率与格式;合理设置 max_buffers | TestStreamFormatCombination |
| CameraMetadata | 精简 settings 中不必要的 Tag;避免重复设置相同值 | TestMetadataConsistency |
| Buffer | 使用 fence 同步;实现 buffer 池复用;减少内存拷贝 | TestBufferFenceLeak |