#include "utils_synchronizer_v2.h" #include #include #include #include namespace av { namespace utils { // 构造函数 SynchronizerV2::SynchronizerV2(const SyncConfigV2& config) : m_config(config) , m_syncStrategy(config.strategy) , m_playbackSpeed(1.0) { // 初始化时钟 initClock(m_audioClock, 0); initClock(m_videoClock, 0); initClock(m_externalClock, 0); // 初始化帧计时器 m_frameTimer = getCurrentTime(); } // 析构函数 SynchronizerV2::~SynchronizerV2() { close(); } // 初始化 ErrorCode SynchronizerV2::initialize() { if (m_initialized) { return ErrorCode::SUCCESS; } // 重置状态 m_initialized = true; m_running = false; m_paused = false; // 重置时钟 initClock(m_audioClock, 0); initClock(m_videoClock, 0); initClock(m_externalClock, 0); // 重置帧计时器 m_frameTimer = getCurrentTime(); // 重置统计信息 std::lock_guard lock(m_statsMutex); m_stats = SyncStatsV2(); return ErrorCode::SUCCESS; } // 关闭 void SynchronizerV2::close() { if (!m_initialized) { return; } stop(); m_initialized = false; } // 启动 ErrorCode SynchronizerV2::start() { if (!m_initialized) { return ErrorCode::NOT_INITIALIZED; } if (m_running) { return ErrorCode::SUCCESS; } // 重置帧计时器 m_frameTimer = getCurrentTime(); // 更新外部时钟 updateExternalClock(); m_running = true; m_paused = false; return ErrorCode::SUCCESS; } // 停止 ErrorCode SynchronizerV2::stop() { if (!m_initialized || !m_running) { return ErrorCode::SUCCESS; } m_running = false; m_paused = false; return ErrorCode::SUCCESS; } // 暂停 ErrorCode SynchronizerV2::pause() { if (!m_initialized || !m_running) { return ErrorCode::NOT_STARTED; } if (m_paused) { return ErrorCode::SUCCESS; } // 设置时钟暂停状态 std::lock_guard lock(m_clockMutex); m_audioClock.paused = true; m_videoClock.paused = true; m_externalClock.paused = true; m_paused = true; return ErrorCode::SUCCESS; } // 恢复 ErrorCode SynchronizerV2::resume() { if (!m_initialized || !m_running) { return ErrorCode::NOT_STARTED; } if (!m_paused) { return ErrorCode::SUCCESS; } // 恢复时钟暂停状态 std::lock_guard lock(m_clockMutex); m_audioClock.paused = false; m_videoClock.paused = false; m_externalClock.paused = false; // 更新外部时钟 updateExternalClock(); m_paused = false; return ErrorCode::SUCCESS; } // 重置 ErrorCode SynchronizerV2::reset() { if (!m_initialized) { return ErrorCode::NOT_INITIALIZED; } // 重置时钟 std::lock_guard lock(m_clockMutex); initClock(m_audioClock, m_audioSerial); initClock(m_videoClock, m_videoSerial); initClock(m_externalClock, m_externalSerial); // 重置帧计时器 m_frameTimer = getCurrentTime(); // 重置音频同步状态 m_audioDiffCum = 0.0; m_audioDiffAvgCount = 0; // 重置统计信息 std::lock_guard statsLock(m_statsMutex); m_stats = SyncStatsV2(); m_stats.playbackSpeed = m_playbackSpeed; return ErrorCode::SUCCESS; } // 设置流信息 void SynchronizerV2::setStreamInfo(bool hasAudio, bool hasVideo) { m_hasAudio = hasAudio; m_hasVideo = hasVideo; // // 如果没有音频,但同步策略是音频主时钟,则切换到视频主时钟 // if (!hasAudio && m_syncStrategy == SyncStrategy::AUDIO_MASTER) { // if (hasVideo) { // setSyncStrategy(SyncStrategy::VIDEO_MASTER); // } else { // setSyncStrategy(SyncStrategy::EXTERNAL_MASTER); // } // } // // 如果没有视频,但同步策略是视频主时钟,则切换到音频主时钟 // if (!hasVideo && m_syncStrategy == SyncStrategy::VIDEO_MASTER) { // if (hasAudio) { // setSyncStrategy(SyncStrategy::AUDIO_MASTER); // } else { // setSyncStrategy(SyncStrategy::EXTERNAL_MASTER); // } // } // 根据可用流调整同步策略 if (hasAudio && hasVideo) { // 两种流都有,使用音频优先 setSyncStrategy(SyncStrategy::AUDIO_MASTER); } else if (hasVideo && !hasAudio) { // 只有视频,强制使用视频主时钟 setSyncStrategy(SyncStrategy::VIDEO_MASTER); } else if (hasAudio && !hasVideo) { // 只有音频,强制使用音频主时钟 setSyncStrategy(SyncStrategy::AUDIO_MASTER); } else { // 两种流都没有,使用外部时钟 setSyncStrategy(SyncStrategy::EXTERNAL_MASTER); } } // 获取时钟值 double SynchronizerV2::getClock(ClockType type) const { std::lock_guard lock(m_clockMutex); const Clock* clock = nullptr; switch (type) { case ClockType::AUDIO: clock = &m_audioClock; break; case ClockType::VIDEO: clock = &m_videoClock; break; case ClockType::EXTERNAL: clock = &m_externalClock; break; } if (!clock) { return 0.0; } // 如果时钟暂停,直接返回pts if (clock->paused) { return clock->pts; } double time = getCurrentTime(); // 计算当前时钟时间 = pts + (当前时间 - 上次更新时间) * 速度 return clock->ptsDrift + (time - clock->lastUpdated) * clock->speed; } // 设置时钟 void SynchronizerV2::setClock(ClockType type, double pts, int serial) { setClockAt(type, pts, serial, getCurrentTime()); } // 在指定时间设置时钟 void SynchronizerV2::setClockAt(ClockType type, double pts, int serial, double time) { std::lock_guard lock(m_clockMutex); Clock* clock = nullptr; switch (type) { case ClockType::AUDIO: clock = &m_audioClock; break; case ClockType::VIDEO: clock = &m_videoClock; break; case ClockType::EXTERNAL: clock = &m_externalClock; break; } if (!clock) { return; } // 更新时钟 clock->pts = pts; clock->lastUpdated = time; clock->ptsDrift = clock->pts - time; clock->serial = serial; // 更新统计信息 //updateStats(); } // 设置时钟速度 void SynchronizerV2::setClockSpeed(ClockType type, double speed) { //std::lock_guard lock(m_clockMutex); Clock* clock = nullptr; switch (type) { case ClockType::AUDIO: clock = &m_audioClock; break; case ClockType::VIDEO: clock = &m_videoClock; break; case ClockType::EXTERNAL: clock = &m_externalClock; break; } if (!clock) { return; } // 设置时钟速度前先更新当前pts double pts = getClock(type); clock->pts = pts; clock->lastUpdated = getCurrentTime(); clock->ptsDrift = clock->pts - clock->lastUpdated; clock->speed = speed; } // 获取主时钟类型 ClockType SynchronizerV2::getMasterClockType() const { // 根据同步策略和流信息确定主时钟类型 switch (m_syncStrategy) { case SyncStrategy::AUDIO_MASTER: if (m_hasAudio) { return ClockType::AUDIO; } break; case SyncStrategy::VIDEO_MASTER: if (m_hasVideo) { return ClockType::VIDEO; } break; case SyncStrategy::EXTERNAL_MASTER: return ClockType::EXTERNAL; } // 如果首选的主时钟不可用,则按优先级选择 if (m_hasAudio) { return ClockType::AUDIO; } else if (m_hasVideo) { return ClockType::VIDEO; } else { return ClockType::EXTERNAL; } } // 获取主时钟值 double SynchronizerV2::getMasterClock() const { ClockType masterType = getMasterClockType(); return getClock(masterType); } // 计算视频帧目标延迟 double SynchronizerV2::computeTargetDelay(double frameDuration, double videoPts) const { double delay = 0.0; // 如果不是视频主时钟,则需要与主时钟同步 if (getMasterClockType() != ClockType::VIDEO) { // 计算视频时钟与主时钟的差异 double diff = videoPts - getMasterClock(); // 如果差异太大(超过noSyncThreshold),则不进行同步 if (std::fabs(diff) < m_config.noSyncThreshold) { // 如果视频落后于主时钟或超前太多,则调整延迟 if (diff <= -m_config.syncThresholdMin) { // 视频落后,减少延迟 delay = std::max(0.0, delay + diff); } else if (diff >= m_config.syncThresholdMax) { // 视频超前太多,增加延迟 delay = delay + diff; } else if (diff >= m_config.syncThresholdMin) { // 视频略微超前,平滑调整 delay = (delay + diff) * 2.0 / 3.0; } } } // 添加帧持续时间 delay += frameDuration; return delay; } // 同步视频帧 FrameDecision SynchronizerV2::synchronizeVideo(double pts, int serial, double duration) const { FrameDecision decision; // 如果没有视频流,直接显示 if (!m_hasVideo) { decision.action = FrameAction::DISPLAY; decision.delay = 0.0; decision.reason = "No video stream"; return decision; } // 如果暂停,直接显示 if (m_paused) { decision.action = FrameAction::DISPLAY; decision.delay = 0.0; decision.reason = "Playback paused"; return decision; } // 计算目标延迟 double delay = computeTargetDelay(duration, pts); // 获取当前时间 double time = getCurrentTime(); // 计算实际延迟(相对于上一帧的显示时间) double actualDelay = time - m_frameTimer; // 计算同步误差 double syncError = 0.0; if (getMasterClockType() != ClockType::VIDEO) { syncError = pts - getMasterClock(); } // 更新帧计时器 m_frameTimer += delay; // 如果实际延迟大于两倍目标延迟,说明系统可能卡顿,重置帧计时器 if (actualDelay > 2.0 * delay) { m_frameTimer = time; } // 决定帧处理动作 if (time < m_frameTimer) { // 当前时间小于下一帧显示时间,需要等待 decision.action = FrameAction::DISPLAY; decision.delay = m_frameTimer - time; // 需要等待的时间 decision.syncError = syncError; decision.reason = "Wait for next frame time"; } else { // 当前时间已经超过下一帧显示时间 // 如果延迟太大,可能需要丢帧 if (time > m_frameTimer + m_config.frameDropThreshold && getMasterClockType() != ClockType::VIDEO) { decision.action = FrameAction::DROP; decision.delay = 0.0; decision.syncError = syncError; decision.reason = "Frame too late, dropping"; // 通知帧丢弃 notifyFrameDrop(ClockType::VIDEO, static_cast(pts * 1000)); } else { // 正常显示 decision.action = FrameAction::DISPLAY; decision.delay = 0.0; // 立即显示 decision.syncError = syncError; decision.reason = "Display immediately"; } } // 通知同步误差 if (std::fabs(syncError) > m_config.syncThresholdMin) { notifySyncError(syncError, decision.reason); } return decision; } // 同步音频 int SynchronizerV2::synchronizeAudio(short* samples, int samplesSize, double pts) { // 如果没有音频流或者音频是主时钟,则不需要同步 if (!m_hasAudio || getMasterClockType() == ClockType::AUDIO || m_paused) { return samplesSize; } // 计算音频与主时钟的差异 double diff = getClock(ClockType::AUDIO) - getMasterClock(); // 如果差异太大,则不进行同步 if (std::fabs(diff) > m_config.noSyncThreshold) { // 重置音频差异累积 m_audioDiffCum = 0.0; m_audioDiffAvgCount = 0; return samplesSize; } // 更新音频差异平均值 m_audioDiffCum = diff + m_audioDiffCum * (1.0 - m_config.audioDiffAvgCoef); if (m_audioDiffAvgCount < m_config.audioDiffAvgCount) { m_audioDiffAvgCount++; } else { double avgDiff = m_audioDiffCum / m_audioDiffAvgCount; // 根据差异调整音频样本数量 if (std::fabs(avgDiff) >= m_config.audioDiffThreshold) { int wantedSamples = samplesSize; int minSamples = samplesSize * (1.0 - m_config.audioDiffThreshold); int maxSamples = samplesSize * (1.0 + m_config.audioDiffThreshold); // 计算调整后的样本数量 wantedSamples += static_cast(diff * samplesSize); wantedSamples = std::max(minSamples, std::min(wantedSamples, maxSamples)); return wantedSamples; } } return samplesSize; } // 设置配置 void SynchronizerV2::setConfig(const SyncConfigV2& config) { m_config = config; m_syncStrategy = config.strategy; } // 获取配置 SyncConfigV2 SynchronizerV2::getConfig() const { return m_config; } // 设置同步策略 void SynchronizerV2::setSyncStrategy(SyncStrategy strategy) { // 检查策略是否可用 if (strategy == SyncStrategy::AUDIO_MASTER && !m_hasAudio) { if (m_hasVideo) { strategy = SyncStrategy::VIDEO_MASTER; } else { strategy = SyncStrategy::EXTERNAL_MASTER; } } else if (strategy == SyncStrategy::VIDEO_MASTER && !m_hasVideo) { if (m_hasAudio) { strategy = SyncStrategy::AUDIO_MASTER; } else { strategy = SyncStrategy::EXTERNAL_MASTER; } } m_syncStrategy = strategy; m_config.strategy = strategy; } // 获取同步策略 SyncStrategy SynchronizerV2::getSyncStrategy() const { return m_syncStrategy; } // 设置播放速度 void SynchronizerV2::setPlaybackSpeed(double speed) { // 限制速度范围 speed = std::max(m_config.clockSpeedMin, std::min(speed, m_config.clockSpeedMax)); // 如果速度没有变化,则不需要更新 if (std::fabs(speed - m_playbackSpeed) < 0.01) { return; } // 更新播放速度 m_playbackSpeed = speed; // 更新所有时钟的速度 setClockSpeed(ClockType::AUDIO, speed); setClockSpeed(ClockType::VIDEO, speed); setClockSpeed(ClockType::EXTERNAL, speed); // 更新统计信息 std::lock_guard lock(m_statsMutex); m_stats.playbackSpeed = speed; } // 获取播放速度 double SynchronizerV2::getPlaybackSpeed() const { return m_playbackSpeed; } // 获取统计信息 SyncStatsV2 SynchronizerV2::getStats() const { std::lock_guard lock(m_statsMutex); return m_stats; } // 设置同步错误回调 void SynchronizerV2::setSyncErrorCallback(const SyncErrorCallback& callback) { std::lock_guard lock(m_callbackMutex); m_syncErrorCallback = callback; } // 设置帧丢弃回调 void SynchronizerV2::setFrameDropCallback(const FrameDropCallback& callback) { std::lock_guard lock(m_callbackMutex); m_frameDropCallback = callback; } // 获取调试信息 std::string SynchronizerV2::getDebugInfo() const { std::stringstream ss; // 获取当前状态 bool initialized = m_initialized; bool running = m_running; bool paused = m_paused; // 获取时钟值 double audioClock = getClock(ClockType::AUDIO); double videoClock = getClock(ClockType::VIDEO); double externalClock = getClock(ClockType::EXTERNAL); double masterClock = getMasterClock(); // 获取同步策略 SyncStrategy strategy = getSyncStrategy(); std::string strategyStr; switch (strategy) { case SyncStrategy::AUDIO_MASTER: strategyStr = "AUDIO_MASTER"; break; case SyncStrategy::VIDEO_MASTER: strategyStr = "VIDEO_MASTER"; break; case SyncStrategy::EXTERNAL_MASTER: strategyStr = "EXTERNAL_MASTER"; break; } // 获取主时钟类型 ClockType masterType = getMasterClockType(); std::string masterTypeStr; switch (masterType) { case ClockType::AUDIO: masterTypeStr = "AUDIO"; break; case ClockType::VIDEO: masterTypeStr = "VIDEO"; break; case ClockType::EXTERNAL: masterTypeStr = "EXTERNAL"; break; } // 获取统计信息 SyncStatsV2 stats = getStats(); // 构建调试信息 ss << "SynchronizerV2 Debug Info:\n"; ss << " State: " << (initialized ? "Initialized" : "Not Initialized") << ", " << (running ? "Running" : "Stopped") << ", " << (paused ? "Paused" : "Playing") << "\n"; ss << " Streams: " << (m_hasAudio ? "Audio" : "No Audio") << ", " << (m_hasVideo ? "Video" : "No Video") << "\n"; ss << " Sync Strategy: " << strategyStr << "\n"; ss << " Master Clock Type: " << masterTypeStr << "\n"; ss << " Clocks (seconds):\n"; ss << " Audio: " << audioClock << "\n"; ss << " Video: " << videoClock << "\n"; ss << " External: " << externalClock << "\n"; ss << " Master: " << masterClock << "\n"; ss << " Playback Speed: " << m_playbackSpeed << "\n"; ss << " Stats:\n"; ss << " Audio-Video Sync Error: " << stats.audioVideoSyncError << " seconds\n"; ss << " Avg Sync Error: " << stats.avgSyncError << " seconds\n"; ss << " Max Sync Error: " << stats.maxSyncError << " seconds\n"; ss << " Dropped Frames: " << stats.droppedFrames << "\n"; ss << " Duplicated Frames: " << stats.duplicatedFrames << "\n"; return ss.str(); } // 初始化时钟 void SynchronizerV2::initClock(Clock& clock, int serial) { clock.pts = 0.0; clock.ptsDrift = 0.0; clock.lastUpdated = getCurrentTime(); clock.speed = m_playbackSpeed; clock.serial = serial; clock.paused = false; clock.queueSerial = serial; } // 将时钟同步到从属时钟 void SynchronizerV2::syncClockToSlave(Clock& c, const Clock& slave) { double clockDiff = getClock(ClockType::EXTERNAL) - getClock(ClockType::AUDIO); double correction = 0.0; // 根据差异调整时钟速度 if (std::fabs(clockDiff) < m_config.noSyncThreshold) { if (clockDiff <= -m_config.syncThresholdMin) { // 外部时钟落后,加速 correction = -m_config.clockSpeedStep; } else if (clockDiff >= m_config.syncThresholdMin) { // 外部时钟超前,减速 correction = m_config.clockSpeedStep; } // 应用速度调整 c.speed = m_playbackSpeed + correction; c.speed = std::max(m_config.clockSpeedMin, std::min(c.speed, m_config.clockSpeedMax)); } } // 更新外部时钟 void SynchronizerV2::updateExternalClock() { // 更新外部时钟,使其与主时钟同步 if (getMasterClockType() != ClockType::EXTERNAL) { double masterClock = getMasterClock(); setClock(ClockType::EXTERNAL, masterClock, m_externalSerial); } } // 检查外部时钟速度 void SynchronizerV2::checkExternalClockSpeed() { if (m_hasAudio && getMasterClockType() == ClockType::EXTERNAL) { // 将外部时钟同步到音频时钟 syncClockToSlave(m_externalClock, m_audioClock); } else if (m_hasVideo && getMasterClockType() == ClockType::EXTERNAL) { // 将外部时钟同步到视频时钟 syncClockToSlave(m_externalClock, m_videoClock); } } // 获取当前时间(秒) double SynchronizerV2::getCurrentTime() const { // 使用av_gettime_relative获取相对时间(微秒),转换为秒 return av_gettime_relative() / 1000000.0; } // 更新统计信息 void SynchronizerV2::updateStats() { std::lock_guard lock(m_statsMutex); // 更新时钟值 m_stats.audioClock = getClock(ClockType::AUDIO); m_stats.videoClock = getClock(ClockType::VIDEO); m_stats.externalClock = getClock(ClockType::EXTERNAL); m_stats.masterClock = getMasterClock(); // 计算音视频同步误差 if (m_hasAudio && m_hasVideo) { m_stats.audioVideoSyncError = m_stats.audioClock - m_stats.videoClock; // 更新平均同步误差 double absError = std::fabs(m_stats.audioVideoSyncError); m_stats.avgSyncError = (m_stats.avgSyncError * 0.9) + (absError * 0.1); // 更新最大同步误差 if (absError > m_stats.maxSyncError) { m_stats.maxSyncError = absError; } } // 更新播放速度 m_stats.playbackSpeed = m_playbackSpeed; } // 通知同步错误 void SynchronizerV2::notifySyncError(double error, const std::string& reason) const { std::lock_guard lock(m_callbackMutex); if (m_syncErrorCallback) { m_syncErrorCallback(error, reason); } } // 通知帧丢弃 void SynchronizerV2::notifyFrameDrop(ClockType type, int64_t pts) const { std::lock_guard lock(m_callbackMutex); if (m_frameDropCallback) { m_frameDropCallback(type, pts); } // 更新统计信息 std::lock_guard statsLock(m_statsMutex); m_stats.droppedFrames++; } } // namespace utils } // namespace av