2. HAL1 关键数据流:Preview 与 Capture 路径

HAL1 架构下,Camera 数据流分为 Preview(预览) 和 Capture(拍照) 两条核心路径。两条路径共享底层硬件资源,但缓冲区管理、帧率控制、同步机制存在显著差异。理解这两条路径的节点与缓冲区流转,是定位性能瓶颈的第一步。

2.1 Preview 数据流路径

Preview 数据流是 HAL1 中最频繁、对延迟最敏感的路径。数据从 Sensor 输出到最终显示,经历以下关键节点:

  1. Sensor 输出:RAW10/RAW12 数据,通过 CSI 接口送入 ISP。
  2. ISP 处理:Bayer 去马赛克、AWB/AE 统计、缩放至预览尺寸(如 1920x1080)。
  3. HAL 接收:HAL 通过 preview_stream_ops 回调从 Gralloc 获取图形缓冲区。
  4. ANativeWindow 队列:缓冲区入队到 SurfaceFlinger 的 BufferQueue。
  5. SurfaceFlinger 合成:合成后送 Display 显示。
性能关键点:Preview 路径的瓶颈通常出现在 ISP 输出到 HAL 接收 的缓冲区传递阶段,以及 ANativeWindow 队列 的 dequeue/buffer 等待时间。
Preview 数据流路径 Sensor ISP 处理 HAL 接收 BufferQueue Display ⚠ 常见瓶颈:ISP 输出帧率不足、HAL 端 dequeueBuffer 阻塞、SurfaceFlinger 合成超时。 建议使用 systrace 抓取 “dequeueBuffer” 和 “queueBuffer” 耗时。

2.2 Capture 数据流路径

Capture 路径在 HAL1 中通常走 单独的高分辨率通道,与 Preview 路径共享 Sensor 但使用独立的 ISP 管线或后处理单元。典型节点如下:

  1. Sensor 全分辨率输出:如 4000x3000 RAW。
  2. ISP 全尺寸处理:YUV 或 JPEG 编码前的预处理。
  3. HAL 拍照回调:takePicture() 触发,HAL 返回 JPEG 或 YUV 数据。
  4. 应用层编码/存储:JPEG 编码、EXIF 写入、文件保存。
注意:HAL1 的 Capture 路径通常 阻塞 Preview 流,直到拍照完成。这是 HAL1 架构的固有缺陷,也是性能优化的重点区域。
Capture 数据流路径 Sensor 全分辨率 ISP 全尺寸处理 HAL 拍照回调 JPEG 编码 存储 ⚠ 典型问题:全分辨率 ISP 处理耗时 > 100ms、JPEG 编码 CPU 占用高、阻塞 Preview 导致 ANR。 优化方向:使用硬件 JPEG 编码器、异步拍照管线、降低全分辨率帧率。

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 编码耗时、内存分配延迟
Preview vs Capture 缓冲区流转对比 Preview 路径 循环队列:3~4 个 buffer 非阻塞,30fps 持续流转 Capture 路径 一次性分配:1~2 个 buffer 阻塞 Preview,单次高延迟 💡 性能优化核心:减少 Capture 路径对 Preview 路径的阻塞时间, 例如通过双 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 后帧率恢复稳定。