#ifndef AVCLOCK_H #define AVCLOCK_H #include "ffmpeg_compat.h" #include "low_latency_config.h" class AVClock { public: AVClock() : m_ptsUs(0) , m_driftUs(0) , m_baseTimeUs(0) , m_frameCount(0) , m_lastResetTimeUs(0) , m_lastClockValueUs(0) {} inline void reset() { m_ptsUs = 0; m_driftUs = 0; m_baseTimeUs = av_gettime_relative(); m_frameCount = 0; m_lastResetTimeUs = m_baseTimeUs; m_lastClockValueUs = 0; } // 修改:接受int64_t微秒时间戳,消除double参数类型 inline void setClock(int64_t ptsUs) { setClockAt(ptsUs); } // 新增:为兼容性提供秒级时间戳设置函数 inline void setClockSeconds(double pts) { int64_t ptsUs = static_cast(pts * 1000000.0); setClock(ptsUs); } // 修改:返回int64_t微秒时间戳,消除double类型和除法运算 inline int64_t getClock() { // 优化:全程使用int64微秒时间戳,避免除法运算 int64_t currentTimeUs = av_gettime_relative(); // 定期重置时间基准,防止累积误差 if (++m_frameCount % LowLatencyConfig::TIMER_RESET_INTERVAL == 0) { resetTimeBase(currentTimeUs); } // 使用整数运算保持精度,避免浮点除法 int64_t elapsedUs = currentTimeUs - m_baseTimeUs; int64_t resultUs = m_driftUs + elapsedUs; // 检测并补偿精度误差(转换为微秒单位) if (m_frameCount > 1) { int64_t driftUs = resultUs - m_lastClockValueUs; if (driftUs > LowLatencyConfig::MAX_ACCEPTABLE_DRIFT_US) { resultUs -= LowLatencyConfig::PRECISION_ERROR_COMPENSATION_US; } } m_lastClockValueUs = resultUs; // 直接返回微秒时间戳,消除除法运算 return resultUs; } // 新增:为兼容性提供秒级时间戳转换函数 inline double getClockSeconds() { return static_cast(getClock()) / 1000000.0; } // 新增:获取高精度微秒时间戳 inline int64_t getClockUs() { int64_t currentTimeUs = av_gettime_relative(); // 定期重置时间基准,防止累积误差 if (++m_frameCount % LowLatencyConfig::TIMER_RESET_INTERVAL == 0) { resetTimeBase(currentTimeUs); } int64_t elapsedUs = currentTimeUs - m_baseTimeUs; int64_t resultUs = m_driftUs + elapsedUs; // 检测并补偿精度误差 if (m_frameCount > 1) { int64_t driftUs = resultUs - m_lastClockValueUs; if (driftUs > LowLatencyConfig::MAX_ACCEPTABLE_DRIFT_US) { resultUs -= LowLatencyConfig::PRECISION_ERROR_COMPENSATION_US; } } m_lastClockValueUs = resultUs; return resultUs; } private: // 修改:接受int64_t微秒时间戳,消除double参数类型 inline void setClockAt(int64_t ptsUs) { // 优化:使用高精度整数时间戳,减少转换误差 int64_t currentTimeUs = av_gettime_relative(); if (m_baseTimeUs == 0) { m_baseTimeUs = currentTimeUs; } // 直接使用微秒时间戳,避免浮点转换 int64_t elapsedUs = currentTimeUs - m_baseTimeUs; m_driftUs = ptsUs - elapsedUs; m_ptsUs = ptsUs; } inline void resetTimeBase(int64_t currentTimeUs) { // 定期重置时间基准,防止长时间运行时的累积误差 if (currentTimeUs - m_lastResetTimeUs > LowLatencyConfig::TIMER_RESET_INTERVAL_US) { // 修复:避免在此处调用 getClockUs() 造成递归/重入 int64_t currentClockUs = m_driftUs + (currentTimeUs - m_baseTimeUs); m_baseTimeUs = currentTimeUs; m_driftUs = currentClockUs; m_lastResetTimeUs = currentTimeUs; } } int64_t m_ptsUs; // 高精度PTS(微秒) int64_t m_driftUs; // 高精度漂移(微秒) int64_t m_baseTimeUs; // 高精度时间基准(微秒) int m_frameCount; // 帧计数器 int64_t m_lastResetTimeUs; // 上次重置时间(微秒) int64_t m_lastClockValueUs; // 上次时钟值(微秒),用于漂移检测 }; #endif // AVCLOCK_H