2. HAL1 关键数据流:Preview 与 Capture 路径
HAL1 架构下,Camera 数据流分为 Preview(预览) 和 Capture(拍照) 两条核心路径。两条路径共享底层硬件资源,但缓冲区管理、帧率控制、同步机制存在显著差异。理解这两条路径的节点与缓冲区流转,是定位性能瓶颈的第一步。
2.1 Preview 数据流路径
Preview 数据流是 HAL1 中最频繁、对延迟最敏感的路径。数据从 Sensor 输出到最终显示,经历以下关键节点:
- Sensor 输出:RAW10/RAW12 数据,通过 CSI 接口送入 ISP。
- ISP 处理:Bayer 去马赛克、AWB/AE 统计、缩放至预览尺寸(如 1920x1080)。
- HAL 接收:HAL 通过
preview_stream_ops回调从 Gralloc 获取图形缓冲区。 - ANativeWindow 队列:缓冲区入队到 SurfaceFlinger 的 BufferQueue。
- SurfaceFlinger 合成:合成后送 Display 显示。
性能关键点:Preview 路径的瓶颈通常出现在 ISP 输出到 HAL 接收 的缓冲区传递阶段,以及 ANativeWindow 队列 的 dequeue/buffer 等待时间。
2.2 Capture 数据流路径
Capture 路径在 HAL1 中通常走 单独的高分辨率通道,与 Preview 路径共享 Sensor 但使用独立的 ISP 管线或后处理单元。典型节点如下:
- Sensor 全分辨率输出:如 4000x3000 RAW。
- ISP 全尺寸处理:YUV 或 JPEG 编码前的预处理。
- HAL 拍照回调:
takePicture()触发,HAL 返回 JPEG 或 YUV 数据。 - 应用层编码/存储:JPEG 编码、EXIF 写入、文件保存。
注意:HAL1 的 Capture 路径通常 阻塞 Preview 流,直到拍照完成。这是 HAL1 架构的固有缺陷,也是性能优化的重点区域。
2.3 数据流中的关键节点与缓冲区管理
HAL1 的缓冲区管理围绕 Gralloc 和 ANativeWindow 展开。以下表格列出关键节点及其缓冲区角色:
| 节点 | 缓冲区类型 | 管理方式 | 性能指标 |
|---|---|---|---|
| Sensor → ISP | RAW 帧 | 硬件 DMA,无显式队列 | 帧率、CSI 带宽 |
| ISP → HAL | YUV/JPEG | Gralloc 分配,HAL 持有引用 | dequeueBuffer 延迟 |
| HAL → BufferQueue | GraphicBuffer | ANativeWindow 队列,最多 3 个 buffer | queueBuffer 耗时、丢帧率 |
| BufferQueue → SurfaceFlinger | GraphicBuffer | Consumer 端 acquire/release | 合成周期、Buffer 等待数 |
| HAL → App (Capture) | JPEG 字节数组 | 直接内存拷贝或共享内存 | 拷贝耗时、内存峰值 |
调优建议:在 HAL1 中,BufferQueue 深度 和 Gralloc 分配策略 是影响 Preview 流畅度的核心参数。建议将 BufferQueue 深度设为 3,并启用
GRALLOC_USAGE_HW_COMPOSER 标志以减少 GPU 拷贝。
2.4 Preview 与 Capture 路径的缓冲区流转对比
两条路径在缓冲区管理上的核心差异如下:
| 维度 | Preview 路径 | Capture 路径 |
|---|---|---|
| 分辨率 | 低(如 1080p) | 高(Sensor 全分辨率) |
| 帧率 | 30fps 或更高 | 单次或低帧率(≤5fps) |
| 缓冲区数量 | 3~4 个(循环队列) | 1~2 个(一次性分配) |
| 阻塞行为 | 非阻塞(异步队列) | 阻塞 Preview 流 |
| 主要瓶颈 | dequeueBuffer 等待、ISP 帧率不足 | JPEG 编码耗时、内存分配延迟 |
2.5 缓冲区管理常见问题与定位方法
- dequeueBuffer 超时:通常由 SurfaceFlinger 消费过慢或 BufferQueue 满导致。使用
dumpsys SurfaceFlinger查看队列状态。 - Buffer 泄漏:HAL 未正确 release buffer,导致 Gralloc 内存耗尽。通过
dumpsys meminfo或libgralloc调试工具定位。 - 帧率抖动:ISP 输出帧率不稳定或 HAL 端处理耗时波动。使用
systrace抓取onFrameAvailable回调间隔。 - 内存带宽瓶颈:高分辨率 Capture 时,DDR 带宽被大量占用。通过
perfetto或simpleperf分析内存访问模式。
实战案例:某平台 Preview 帧率从 30fps 掉到 15fps,定位发现是 BufferQueue 深度不足(仅 2 个 buffer)导致 dequeueBuffer 频繁阻塞。将深度改为 3 后帧率恢复稳定。