3. Capture链路基础:Capture Session的建立、Request与Result的同步模型、Frame Number与Timestamp管理
Capture链路是Camera HAL框架中负责高画质、高分辨率单帧或连拍的核心路径,与Preview链路追求低延迟不同,Capture链路更关注帧的完整性、参数精确性以及多帧同步。本章将深入剖析Capture Session的完整生命周期、Request与Result的同步模型,以及Frame Number与Timestamp这两个关键标识符的管理机制。
3.1 Capture Session的建立流程
Capture Session是Camera HAL中一次拍摄任务的逻辑容器,它管理着从配置到销毁的完整资源集合。Session的建立涉及Framework、HAL Service与HAL层的多次握手。
3.1.1 Session建立的核心步骤
- 配置输出流(ConfigureStreams): Framework通过
ICameraDevice::configureStreams向HAL提交输出流配置,包括流类型(YUV、JPEG、RAW)、分辨率、格式、使用场景(PREVIEW、STILL_CAPTURE、VIDEO_RECORDING等)。 - 分配Stream缓冲区(AllocateBuffers): HAL根据配置为每个Stream分配内部缓冲区池,包括Gralloc Buffer Handle和HAL内部元数据缓冲区。
- 创建Session(ConstructDefaultRequestSettings): Framework调用
ICameraDeviceSession::constructDefaultRequestSettings获取默认的Capture Request模板(如TEMPLATE_STILL_CAPTURE)。 - 初始化Pipeline: HAL内部创建ISP Pipeline、Sensor配置、3A算法实例等硬件资源。
- 返回Session Handle: HAL返回一个
CameraCaptureSession实例给Framework,此时Session进入就绪状态。
3.1.2 Session状态转换图
以下SVG图展示了Capture Session从创建到销毁的完整状态机,包含关键状态节点和转换条件。
3.2 Request与Result的同步模型
Capture链路的核心交互模式是异步请求-响应模型。Framework向HAL提交一个Capture Request,HAL在完成帧处理后返回一个Capture Result。这种模型允许Pipeline深度流水线化,但也带来了同步管理的复杂性。
3.2.1 请求与响应的生命周期
| 阶段 | 操作 | 关键数据结构 | 同步点 |
|---|---|---|---|
| 1. 请求提交 | Framework调用capture()或captureBurst() |
CaptureRequest (包含settings, outputTargets) |
入队到HAL工作队列 |
| 2. 请求处理 | HAL解析Request,配置Sensor/ISP/3A | CameraMetadata (AE/AF/AWB参数) |
硬件触发VSYNC |
| 3. 帧捕获 | Sensor曝光,ISP处理RAW→YUV/JPEG | CaptureResult (partial结果) |
逐帧完成回调 |
| 4. 结果返回 | HAL通过processCaptureResult()回调 |
CaptureResult (完整结果 + 缓冲区) |
Framework释放Request |
3.2.2 同步模型详解
同步模型的核心是Frame Number作为唯一标识符,将Request与Result一一对应。HAL必须保证每个提交的Request最终都会返回一个Result,且Result中的Frame Number必须与Request一致。
3.2.3 同步模型流程图
以下SVG图展示了Request与Result在时间轴上的同步关系,包含Partial Result与Final Result的区分。
3.3 Frame Number与Timestamp管理
Frame Number和Timestamp是Capture链路中两个最核心的元数据标识符,它们贯穿整个Pipeline,用于帧追踪、同步、性能分析和调试。
3.3.1 Frame Number管理
Frame Number是一个单调递增的32位无符号整数,由Framework在创建Request时分配。HAL必须保证:
- 唯一性: 在同一个Session生命周期内,每个Request的Frame Number唯一。
- 有序性: 提交的Request的Frame Number必须严格递增。
- 回传一致性: Result中的Frame Number必须与Request一致。
- 溢出处理: 当Frame Number达到最大值(0xFFFFFFFF)后,回绕到0重新开始,但Framework会确保在回绕前所有旧Request都已处理完毕。
3.3.2 Timestamp管理
Timestamp是帧曝光开始时刻的精确时间戳,单位纳秒(ns),使用CLOCK_MONOTONIC时钟源。Timestamp在以下场景中至关重要:
| 使用场景 | 作用 | 精度要求 |
|---|---|---|
| 帧率计算 | 通过相邻帧Timestamp差值计算实际帧率 | ±1ms |
| 多Camera同步 | 对齐多路Sensor的曝光时间点 | ±100μs |
| 3A算法 | AE/AF/AWb需要精确的帧时间戳进行预测 | ±500μs |
| 视频编码 | 编码器根据Timestamp生成PTS/DTS | ±1μs |
| 性能分析 | 计算Pipeline端到端延迟 | ±100μs |
3.3.3 Frame Number与Timestamp的关联模型
以下SVG图展示了Frame Number与Timestamp在Pipeline中的生成、传递和关联关系,包含Sensor、ISP、HAL和Framework四个层级。
3.4 性能调优要点
基于上述基础,在Capture链路性能调优中需要重点关注以下方面:
- Session建立延迟: 从configureStreams到Session就绪的时间,应控制在50ms以内。
- Request提交到Result返回延迟: 端到端延迟,单帧Capture应小于100ms。
- Frame Number连续性: 检查是否有跳号或重复,异常跳号通常意味着HAL内部丢帧。
- Timestamp抖动: 相邻帧Timestamp差值的标准差,应小于帧间隔的10%。
3.4.1 常见问题与解决方案
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| Session建立超时 | ISP Pipeline初始化过慢,或缓冲区分配失败 | 预分配缓冲区池,延迟初始化非关键组件 |
| Result返回乱序 | HAL内部多线程处理未做重排 | 在HAL层增加Frame Number排序队列 |
| Timestamp跳变 | Sensor驱动时间戳读取位置错误 | 确保在VSYNC中断中读取硬件时间戳 |
| Frame Number回绕异常 | HAL未正确处理溢出场景 | 在HAL层增加回绕检测逻辑 |
3.4.2 调试命令示例
在Android平台上,可以使用以下命令监控Capture链路的关键指标:
# 查看Camera HAL的帧统计信息
adb shell dumpsys media.camera | grep -A 20 "CaptureSession"
# 监控Frame Number连续性
adb logcat -s CameraFramework | grep "frameNumber"
# 查看Timestamp分布
adb shell dumpsys media.camera | grep "timestamp"
# 启用HAL层性能跟踪
adb shell setprop persist.vendor.camera.perf 1
adb logcat -s CameraHAL | grep "PERF"