Android CameraServer PreviewFrameSpacer梳理

📅 2026/7/23 21:16:03 👁️ 阅读次数 📝 编程学习
Android CameraServer PreviewFrameSpacer梳理

PreviewFrameSpacer 设计与实现

文件位置:device3/PreviewFrameSpacer.h/PreviewFrameSpacer.cpp


1. 问题背景

理想情况下,预览帧应按传感器输出节奏呈现给用户。但实际中,CPU 负载、请求设置差异等因素导致帧处理延迟不均匀,造成预览帧间距忽大忽小,用户感知到卡顿。


2. 核心设计

PreviewFrameSpacer 继承Thread,运行在独立线程中:

Camera3OutputStream::returnBufferCheckedLocked() │ (HAL 返回 buffer) ▼ PreviewFrameSpacer::queuePreviewBuffer() │ 入队到 mPendingBuffers ▼ PreviewFrameSpacer::threadLoop() [独立线程] ├── 等待 buffer 到达 ├── 计算 readoutInterval = 当前帧 readoutTimestamp - 上一帧 readoutTimestamp ├── if readoutInterval >= 80ms: 直接入队(帧间距过大,不等待) ├── else: 按 readoutInterval 节奏等待后入队 └── queueBufferToClientLocked() → mConsumer->queueBuffer()

3. 关键常量

常量含义
kWaitDuration50ms无 buffer 时的等待超时
kFrameIntervalThreshold80ms帧间距阈值,超过则直接入队
kMaxFrameWaitTime10ms最大等待时间,避免过度延迟
kFrameAdjustThreshold2ms提前量,补偿代码执行时间

4. threadLoop() 核心逻辑

boolPreviewFrameSpacer::threadLoop(){// 1. 无 buffer 时等待 50msif(mPendingBuffers.empty()){mBufferCond.waitRelative(mLock,kWaitDuration);returntrue;}// 2. 计算与上一帧的 readout 间隔nsecs_t readoutInterval=buffer.readoutTimestamp-mLastCameraReadoutTime;// 3. 间隔 >= 80ms: 直接入队(非连续预览帧)if(readoutInterval>=kFrameIntervalThreshold){queueBufferToClientLocked(buffer,currentTime);returntrue;