| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756 |
- #include "utils_synchronizer_v2.h"
- #include <algorithm>
- #include <cmath>
- #include <iostream>
- #include <sstream>
- 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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<std::mutex> 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;
- return clock->ptsDrift + time + (time - clock->lastUpdated) * (1.0 - 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<std::mutex> 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<std::mutex> 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<int64_t>(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<int>(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<std::mutex> lock(m_statsMutex);
- m_stats.playbackSpeed = speed;
- }
- // 获取播放速度
- double SynchronizerV2::getPlaybackSpeed() const {
- return m_playbackSpeed;
- }
- // 获取统计信息
- SyncStatsV2 SynchronizerV2::getStats() const {
- std::lock_guard<std::mutex> lock(m_statsMutex);
- return m_stats;
- }
- // 设置同步错误回调
- void SynchronizerV2::setSyncErrorCallback(const SyncErrorCallback& callback) {
- std::lock_guard<std::mutex> lock(m_callbackMutex);
- m_syncErrorCallback = callback;
- }
- // 设置帧丢弃回调
- void SynchronizerV2::setFrameDropCallback(const FrameDropCallback& callback) {
- std::lock_guard<std::mutex> lock(m_callbackMutex);
- m_frameDropCallback = callback;
- }
- // 获取调试信息
- std::string SynchronizerV2::getDebugInfo() const {
- std::stringstream ss;
- ss.precision(4);
- // 获取当前状态
- 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
- {
- return av_gettime_relative() / 1000000.0;
- }
- // 更新统计信息
- void SynchronizerV2::updateStats() {
- std::lock_guard<std::mutex> 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<std::mutex> lock(m_callbackMutex);
- if (m_syncErrorCallback) {
- m_syncErrorCallback(error, reason);
- }
- }
- // 通知帧丢弃
- void SynchronizerV2::notifyFrameDrop(ClockType type, int64_t pts) const {
- std::lock_guard<std::mutex> lock(m_callbackMutex);
- if (m_frameDropCallback) {
- m_frameDropCallback(type, pts);
- }
-
- // 更新统计信息
- std::lock_guard<std::mutex> statsLock(m_statsMutex);
- m_stats.droppedFrames++;
- }
- } // namespace utils
- } // namespace av
|