4. 视频录制流畅度提升

任务说明

在Android相机HAL层,视频录制帧率不稳定通常源于3A算法(自动曝光/自动白平衡/自动对焦)的频繁收敛、传感器输出帧间隔抖动以及ISP管线处理延迟波动。本案例目标是通过调整HAL层参数,使视频录制时帧率稳定在目标值(如30fps)附近,帧间隔抖动控制在±1ms以内。

核心实现

以下代码实现一个HAL层帧率稳定性控制模块,包含三个关键机制:帧间隔统计与抖动检测、3A收敛抑制、动态帧间隔补偿。该模块可直接集成到HAL的StreamingProcessor中。

// frame_rate_stabilizer.h
#ifndef FRAME_RATE_STABILIZER_H
#define FRAME_RATE_STABILIZER_H

#include <chrono>
#include <deque>
#include <mutex>
#include <cstdint>

namespace android {
namespace camera_hal {

struct FrameStabilizeConfig {
    uint32_t target_fps = 30;           // 目标帧率
    uint32_t frame_interval_us = 33333; // 目标帧间隔(微秒)
    uint32_t jitter_tolerance_us = 1000; // 抖动容忍度(±1ms)
    uint32_t max_3a_converge_frames = 5; // 3A收敛期间最多跳过的帧数
    bool enable_3a_stall = true;        // 是否启用3A收敛抑制
};

class FrameRateStabilizer {
public:
    explicit FrameRateStabilizer(const FrameStabilizeConfig& config)
        : config_(config) {}

    // 在HAL层每次出帧前调用,返回是否应丢弃当前帧
    bool ShouldDropFrame(uint64_t frame_timestamp_us) {
        std::lock_guard<std::mutex> lock(mutex_);
        uint64_t now_us = frame_timestamp_us;
        
        if (last_frame_time_us_ == 0) {
            last_frame_time_us_ = now_us;
            return false;
        }
        
        uint64_t actual_interval = now_us - last_frame_time_us_;
        last_frame_time_us_ = now_us;
        
        // 记录最近60帧的间隔用于统计
        intervals_.push_back(actual_interval);
        if (intervals_.size() > 60) {
            intervals_.pop_front();
        }
        
        // 判断当前帧间隔是否超出容忍范围
        int64_t delta = static_cast<int64_t>(actual_interval) - 
                        static_cast<int64_t>(config_.frame_interval_us);
        if (delta < 0) delta = -delta;
        
        // 帧间隔过短(帧率过高),丢弃当前帧以稳定节奏
        if (delta > config_.jitter_tolerance_us && 
            actual_interval < config_.frame_interval_us) {
            dropped_frames_++;
            return true;
        }
        
        return false;
    }

    // 3A收敛期间调用,抑制不必要的曝光/白平衡调整
    void On3AConverging(bool is_converging) {
        std::lock_guard<std::mutex> lock(mutex_);
        if (is_converging) {
            converge_frame_count_ = 0;
            is_3a_active_ = true;
        } else {
            is_3a_active_ = false;
        }
    }

    // 获取当前帧率稳定性统计
    struct StabilityStats {
        float avg_interval_us;
        float jitter_us;
        uint32_t dropped_frames;
        uint32_t total_frames;
    };
    
    StabilityStats GetStats() {
        std::lock_guard<std::mutex> lock(mutex_);
        StabilityStats stats;
        stats.dropped_frames = dropped_frames_;
        stats.total_frames = total_frames_;
        
        if (intervals_.empty()) {
            stats.avg_interval_us = 0;
            stats.jitter_us = 0;
            return stats;
        }
        
        // 计算平均帧间隔
        uint64_t sum = 0;
        for (auto interval : intervals_) {
            sum += interval;
        }
        stats.avg_interval_us = static_cast<float>(sum) / intervals_.size();
        
        // 计算标准差作为抖动指标
        float mean = stats.avg_interval_us;
        float variance_sum = 0;
        for (auto interval : intervals_) {
            float diff = static_cast<float>(interval) - mean;
            variance_sum += diff * diff;
        }
        stats.jitter_us = sqrt(variance_sum / intervals_.size());
        
        return stats;
    }

private:
    FrameStabilizeConfig config_;
    std::mutex mutex_;
    uint64_t last_frame_time_us_ = 0;
    std::deque<uint64_t> intervals_;
    uint32_t dropped_frames_ = 0;
    uint32_t total_frames_ = 0;
    bool is_3a_active_ = false;
    uint32_t converge_frame_count_ = 0;
};

} // namespace camera_hal
} // namespace android

#endif // FRAME_RATE_STABILIZER_H

集成到HAL管线

在HAL的StreamingProcessor中,按以下方式调用帧率稳定器:

// StreamingProcessor.cpp 关键片段
#include "frame_rate_stabilizer.h"

using android::camera_hal::FrameRateStabilizer;
using android::camera_hal::FrameStabilizeConfig;

// 初始化时配置
FrameStabilizeConfig config;
config.target_fps = 30;
config.frame_interval_us = 33333;
config.jitter_tolerance_us = 1000;
config.enable_3a_stall = true;

FrameRateStabilizer stabilizer_(config);

// 在3A状态变化时通知
void On3AStateChanged(bool converging) {
    stabilizer_.On3AConverging(converging);
}

// 在每次出帧前调用
bool ShouldOutputFrame(uint64_t timestamp_us) {
    // 3A收敛期间,前5帧允许跳过以等待稳定
    if (config_.enable_3a_stall && is_3a_converging_) {
        if (converge_skip_count_ < config_.max_3a_converge_frames) {
            converge_skip_count_++;
            return false; // 跳过当前帧
        }
    }
    
    // 帧间隔抖动检测
    if (stabilizer_.ShouldDropFrame(timestamp_us)) {
        return false; // 丢弃过快到达的帧
    }
    
    return true;
}

验证方法

完成集成后,通过以下步骤验证帧率稳定性:

  1. 构建与部署:编译HAL并刷入设备,或使用模拟器运行。
  2. 录制测试:使用Camera2 API开启30fps视频录制,持续录制60秒,场景包含固定光照和缓慢移动物体。
  3. 数据采集:通过dumpsys media.camera或HAL日志获取每帧的时间戳,计算实际帧间隔。
  4. 判定标准:平均帧率在29.5~30.5fps范围内,帧间隔标准差小于1000μs(即±1ms抖动),且无连续丢帧超过2帧。

若帧间隔抖动仍超出容忍范围,可调整jitter_tolerance_us参数(建议范围500~2000μs),或检查传感器驱动是否存在时钟漂移问题。