utils_synchronizer_v2.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762
  1. #include "utils_synchronizer_v2.h"
  2. #include "qdebug.h"
  3. #include "qglobal.h"
  4. #include <algorithm>
  5. #include <cmath>
  6. #include <iostream>
  7. #include <sstream>
  8. namespace av {
  9. namespace utils {
  10. // 构造函数
  11. SynchronizerV2::SynchronizerV2(const SyncConfigV2& config)
  12. : m_config(config)
  13. , m_syncStrategy(config.strategy)
  14. , m_playbackSpeed(1.0)
  15. {
  16. // 初始化时钟
  17. initClock(m_audioClock, 0);
  18. initClock(m_videoClock, 0);
  19. initClock(m_externalClock, 0);
  20. // 初始化帧计时器
  21. m_frameTimer = getCurrentTime();
  22. }
  23. // 析构函数
  24. SynchronizerV2::~SynchronizerV2() {
  25. close();
  26. }
  27. // 初始化
  28. ErrorCode SynchronizerV2::initialize() {
  29. if (m_initialized) {
  30. return ErrorCode::SUCCESS;
  31. }
  32. // 重置状态
  33. m_initialized = true;
  34. m_running = false;
  35. m_paused = false;
  36. // 重置时钟
  37. initClock(m_audioClock, 0);
  38. initClock(m_videoClock, 0);
  39. initClock(m_externalClock, 0);
  40. // 重置帧计时器
  41. m_frameTimer = getCurrentTime();
  42. // 重置统计信息
  43. std::lock_guard<std::mutex> lock(m_statsMutex);
  44. m_stats = SyncStatsV2();
  45. return ErrorCode::SUCCESS;
  46. }
  47. // 关闭
  48. void SynchronizerV2::close() {
  49. if (!m_initialized) {
  50. return;
  51. }
  52. stop();
  53. m_initialized = false;
  54. }
  55. // 启动
  56. ErrorCode SynchronizerV2::start() {
  57. if (!m_initialized) {
  58. return ErrorCode::NOT_INITIALIZED;
  59. }
  60. if (m_running) {
  61. return ErrorCode::SUCCESS;
  62. }
  63. // 重置帧计时器
  64. m_frameTimer = getCurrentTime();
  65. // 更新外部时钟
  66. updateExternalClock();
  67. m_running = true;
  68. m_paused = false;
  69. return ErrorCode::SUCCESS;
  70. }
  71. // 停止
  72. ErrorCode SynchronizerV2::stop() {
  73. if (!m_initialized || !m_running) {
  74. return ErrorCode::SUCCESS;
  75. }
  76. m_running = false;
  77. m_paused = false;
  78. return ErrorCode::SUCCESS;
  79. }
  80. // 暂停
  81. ErrorCode SynchronizerV2::pause() {
  82. if (!m_initialized || !m_running) {
  83. return ErrorCode::NOT_STARTED;
  84. }
  85. if (m_paused) {
  86. return ErrorCode::SUCCESS;
  87. }
  88. {
  89. // 设置时钟暂停状态
  90. std::lock_guard<std::mutex> lock(m_clockMutex);
  91. m_audioClock.paused = true;
  92. m_videoClock.paused = true;
  93. m_externalClock.paused = true;
  94. }
  95. m_paused = true;
  96. return ErrorCode::SUCCESS;
  97. }
  98. // 恢复
  99. ErrorCode SynchronizerV2::resume() {
  100. if (!m_initialized || !m_running) {
  101. return ErrorCode::NOT_STARTED;
  102. }
  103. if (!m_paused) {
  104. return ErrorCode::SUCCESS;
  105. }
  106. // 防止互斥死锁
  107. {
  108. // 恢复时钟暂停状态
  109. std::lock_guard<std::mutex> lock(m_clockMutex);
  110. m_audioClock.paused = false;
  111. m_videoClock.paused = false;
  112. m_externalClock.paused = false;
  113. }
  114. // 更新外部时钟
  115. updateExternalClock();
  116. m_paused = false;
  117. return ErrorCode::SUCCESS;
  118. }
  119. // 重置
  120. ErrorCode SynchronizerV2::reset() {
  121. if (!m_initialized) {
  122. return ErrorCode::NOT_INITIALIZED;
  123. }
  124. // 重置时钟
  125. std::lock_guard<std::mutex> lock(m_clockMutex);
  126. initClock(m_audioClock, m_audioSerial);
  127. initClock(m_videoClock, m_videoSerial);
  128. initClock(m_externalClock, m_externalSerial);
  129. // 重置帧计时器
  130. m_frameTimer = getCurrentTime();
  131. // 重置音频同步状态
  132. m_audioDiffCum = 0.0;
  133. m_audioDiffAvgCount = 0;
  134. // 重置统计信息
  135. {
  136. std::lock_guard<std::mutex> statsLock(m_statsMutex);
  137. m_stats = SyncStatsV2();
  138. m_stats.playbackSpeed = m_playbackSpeed;
  139. }
  140. return ErrorCode::SUCCESS;
  141. }
  142. // 设置流信息
  143. void SynchronizerV2::setStreamInfo(bool hasAudio, bool hasVideo) {
  144. m_hasAudio = hasAudio;
  145. m_hasVideo = hasVideo;
  146. // // 如果没有音频,但同步策略是音频主时钟,则切换到视频主时钟
  147. // if (!hasAudio && m_syncStrategy == SyncStrategy::AUDIO_MASTER) {
  148. // if (hasVideo) {
  149. // setSyncStrategy(SyncStrategy::VIDEO_MASTER);
  150. // } else {
  151. // setSyncStrategy(SyncStrategy::EXTERNAL_MASTER);
  152. // }
  153. // }
  154. // // 如果没有视频,但同步策略是视频主时钟,则切换到音频主时钟
  155. // if (!hasVideo && m_syncStrategy == SyncStrategy::VIDEO_MASTER) {
  156. // if (hasAudio) {
  157. // setSyncStrategy(SyncStrategy::AUDIO_MASTER);
  158. // } else {
  159. // setSyncStrategy(SyncStrategy::EXTERNAL_MASTER);
  160. // }
  161. // }
  162. // 根据可用流调整同步策略
  163. if (hasAudio && hasVideo) {
  164. // 两种流都有,使用音频优先
  165. setSyncStrategy(SyncStrategy::AUDIO_MASTER);
  166. } else if (hasVideo && !hasAudio) {
  167. // 只有视频,强制使用视频主时钟
  168. setSyncStrategy(SyncStrategy::VIDEO_MASTER);
  169. } else if (hasAudio && !hasVideo) {
  170. // 只有音频,强制使用音频主时钟
  171. setSyncStrategy(SyncStrategy::AUDIO_MASTER);
  172. } else {
  173. // 两种流都没有,使用外部时钟
  174. setSyncStrategy(SyncStrategy::EXTERNAL_MASTER);
  175. }
  176. }
  177. // 获取时钟值
  178. double SynchronizerV2::getClock(ClockType type) const {
  179. std::lock_guard<std::mutex> lock(m_clockMutex);
  180. const Clock* clock = nullptr;
  181. switch (type) {
  182. case ClockType::AUDIO:
  183. clock = &m_audioClock;
  184. break;
  185. case ClockType::VIDEO:
  186. clock = &m_videoClock;
  187. break;
  188. case ClockType::EXTERNAL:
  189. clock = &m_externalClock;
  190. break;
  191. }
  192. if (!clock) {
  193. return 0.0;
  194. }
  195. // 如果时钟暂停,直接返回pts
  196. if (clock->paused) {
  197. return clock->pts;
  198. }
  199. double time = getCurrentTime();
  200. // 计算当前时钟时间 = pts + (当前时间 - 上次更新时间) * 速度
  201. // return clock->ptsDrift + (time - clock->lastUpdated) * clock->speed;
  202. return clock->ptsDrift + time + (time - clock->lastUpdated) * (1.0 - clock->speed);
  203. }
  204. // 设置时钟
  205. void SynchronizerV2::setClock(ClockType type, double pts, int serial) {
  206. setClockAt(type, pts, serial, getCurrentTime());
  207. }
  208. // 在指定时间设置时钟
  209. void SynchronizerV2::setClockAt(ClockType type, double pts, int serial, double time) {
  210. std::lock_guard<std::mutex> lock(m_clockMutex);
  211. if (m_paused) {
  212. qDebug() << "setClockAt-->:" << (int) type << pts << serial << time;
  213. }
  214. Clock* clock = nullptr;
  215. switch (type) {
  216. case ClockType::AUDIO:
  217. clock = &m_audioClock;
  218. break;
  219. case ClockType::VIDEO:
  220. clock = &m_videoClock;
  221. break;
  222. case ClockType::EXTERNAL:
  223. clock = &m_externalClock;
  224. break;
  225. }
  226. if (!clock) {
  227. return;
  228. }
  229. // 更新时钟
  230. clock->pts = pts;
  231. clock->lastUpdated = time;
  232. clock->ptsDrift = clock->pts - time;
  233. clock->serial = serial;
  234. // 更新统计信息
  235. //updateStats();
  236. }
  237. // 设置时钟速度
  238. void SynchronizerV2::setClockSpeed(ClockType type, double speed) {
  239. //std::lock_guard<std::mutex> lock(m_clockMutex);
  240. Clock* clock = nullptr;
  241. switch (type) {
  242. case ClockType::AUDIO:
  243. clock = &m_audioClock;
  244. break;
  245. case ClockType::VIDEO:
  246. clock = &m_videoClock;
  247. break;
  248. case ClockType::EXTERNAL:
  249. clock = &m_externalClock;
  250. break;
  251. }
  252. if (!clock) {
  253. return;
  254. }
  255. // 设置时钟速度前先更新当前pts
  256. double pts = getClock(type);
  257. clock->pts = pts;
  258. clock->lastUpdated = getCurrentTime();
  259. clock->ptsDrift = clock->pts - clock->lastUpdated;
  260. clock->speed = speed;
  261. }
  262. // 获取主时钟类型
  263. ClockType SynchronizerV2::getMasterClockType() const {
  264. // 根据同步策略和流信息确定主时钟类型
  265. switch (m_syncStrategy) {
  266. case SyncStrategy::AUDIO_MASTER:
  267. if (m_hasAudio) {
  268. return ClockType::AUDIO;
  269. }
  270. break;
  271. case SyncStrategy::VIDEO_MASTER:
  272. if (m_hasVideo) {
  273. return ClockType::VIDEO;
  274. }
  275. break;
  276. case SyncStrategy::EXTERNAL_MASTER:
  277. return ClockType::EXTERNAL;
  278. }
  279. // 如果首选的主时钟不可用,则按优先级选择
  280. if (m_hasAudio) {
  281. return ClockType::AUDIO;
  282. } else if (m_hasVideo) {
  283. return ClockType::VIDEO;
  284. } else {
  285. return ClockType::EXTERNAL;
  286. }
  287. }
  288. // 获取主时钟值
  289. double SynchronizerV2::getMasterClock() const {
  290. ClockType masterType = getMasterClockType();
  291. return getClock(masterType);
  292. }
  293. // 计算视频帧目标延迟
  294. double SynchronizerV2::computeTargetDelay(double frameDuration, double videoPts) const {
  295. double delay = 0.0;
  296. // 如果不是视频主时钟,则需要与主时钟同步
  297. if (getMasterClockType() != ClockType::VIDEO) {
  298. // 计算视频时钟与主时钟的差异
  299. double diff = videoPts - getMasterClock();
  300. // 如果差异太大(超过noSyncThreshold),则不进行同步
  301. if (std::fabs(diff) < m_config.noSyncThreshold) {
  302. // 如果视频落后于主时钟或超前太多,则调整延迟
  303. if (diff <= -m_config.syncThresholdMin) { // 视频落后,减少延迟
  304. delay = std::max(0.0, delay + diff);
  305. } else if (diff >= m_config.syncThresholdMax) { // 视频超前太多,增加延迟
  306. delay = delay + diff;
  307. } else if (diff >= m_config.syncThresholdMin) { // 视频略微超前,平滑调整
  308. delay = (delay + diff) * 2.0 / 3.0;
  309. }
  310. }
  311. }
  312. // 添加帧持续时间
  313. delay += frameDuration;
  314. return delay;
  315. }
  316. // 同步视频帧
  317. FrameDecision SynchronizerV2::synchronizeVideo(double pts, int serial, double duration) const {
  318. FrameDecision decision;
  319. // 如果没有视频流,直接显示
  320. if (!m_hasVideo) {
  321. decision.action = FrameAction::DISPLAY;
  322. decision.delay = 0.0;
  323. decision.reason = "No video stream";
  324. return decision;
  325. }
  326. // 如果暂停,直接显示
  327. if (m_paused) {
  328. decision.action = FrameAction::DISPLAY;
  329. decision.delay = 0.0;
  330. decision.reason = "Playback paused";
  331. return decision;
  332. }
  333. // 计算目标延迟
  334. double delay = computeTargetDelay(duration, pts);
  335. // 获取当前时间
  336. double time = getCurrentTime();
  337. // 计算实际延迟(相对于上一帧的显示时间)
  338. double actualDelay = time - m_frameTimer;
  339. // 计算同步误差
  340. double syncError = 0.0;
  341. if (getMasterClockType() != ClockType::VIDEO) {
  342. syncError = pts - getMasterClock();
  343. }
  344. // 更新帧计时器
  345. m_frameTimer += delay;
  346. // 如果实际延迟大于两倍目标延迟,说明系统可能卡顿,重置帧计时器
  347. if (actualDelay > 2.0 * delay) {
  348. m_frameTimer = time;
  349. }
  350. // 决定帧处理动作
  351. if (time < m_frameTimer) {
  352. // 当前时间小于下一帧显示时间,需要等待
  353. decision.action = FrameAction::DISPLAY;
  354. decision.delay = m_frameTimer - time; // 需要等待的时间
  355. decision.syncError = syncError;
  356. decision.reason = "Wait for next frame time";
  357. } else {
  358. // 当前时间已经超过下一帧显示时间
  359. // 如果延迟太大,可能需要丢帧
  360. if (time > m_frameTimer + m_config.frameDropThreshold && getMasterClockType() != ClockType::VIDEO) {
  361. decision.action = FrameAction::DROP;
  362. decision.delay = 0.0;
  363. decision.syncError = syncError;
  364. decision.reason = "Frame too late, dropping";
  365. // 通知帧丢弃
  366. notifyFrameDrop(ClockType::VIDEO, static_cast<int64_t>(pts * 1000));
  367. } else {
  368. // 正常显示
  369. decision.action = FrameAction::DISPLAY;
  370. decision.delay = 0.0; // 立即显示
  371. decision.syncError = syncError;
  372. decision.reason = "Display immediately";
  373. }
  374. }
  375. // 通知同步误差
  376. if (std::fabs(syncError) > m_config.syncThresholdMin) {
  377. notifySyncError(syncError, decision.reason);
  378. }
  379. return decision;
  380. }
  381. // 同步音频
  382. int SynchronizerV2::synchronizeAudio(short* samples, int samplesSize, double pts) {
  383. // 如果没有音频流或者音频是主时钟,则不需要同步
  384. if (!m_hasAudio || getMasterClockType() == ClockType::AUDIO || m_paused) {
  385. return samplesSize;
  386. }
  387. // 计算音频与主时钟的差异
  388. double diff = getClock(ClockType::AUDIO) - getMasterClock();
  389. // 如果差异太大,则不进行同步
  390. if (std::fabs(diff) > m_config.noSyncThreshold) {
  391. // 重置音频差异累积
  392. m_audioDiffCum = 0.0;
  393. m_audioDiffAvgCount = 0;
  394. return samplesSize;
  395. }
  396. // 更新音频差异平均值
  397. m_audioDiffCum = diff + m_audioDiffCum * (1.0 - m_config.audioDiffAvgCoef);
  398. if (m_audioDiffAvgCount < m_config.audioDiffAvgCount) {
  399. m_audioDiffAvgCount++;
  400. } else {
  401. double avgDiff = m_audioDiffCum / m_audioDiffAvgCount;
  402. // 根据差异调整音频样本数量
  403. if (std::fabs(avgDiff) >= m_config.audioDiffThreshold) {
  404. int wantedSamples = samplesSize;
  405. int minSamples = samplesSize * (1.0 - m_config.audioDiffThreshold);
  406. int maxSamples = samplesSize * (1.0 + m_config.audioDiffThreshold);
  407. // 计算调整后的样本数量
  408. wantedSamples += static_cast<int>(diff * samplesSize);
  409. wantedSamples = std::max(minSamples, std::min(wantedSamples, maxSamples));
  410. return wantedSamples;
  411. }
  412. }
  413. return samplesSize;
  414. }
  415. // 设置配置
  416. void SynchronizerV2::setConfig(const SyncConfigV2& config) {
  417. m_config = config;
  418. m_syncStrategy = config.strategy;
  419. }
  420. // 获取配置
  421. SyncConfigV2 SynchronizerV2::getConfig() const {
  422. return m_config;
  423. }
  424. // 设置同步策略
  425. void SynchronizerV2::setSyncStrategy(SyncStrategy strategy) {
  426. // 检查策略是否可用
  427. if (strategy == SyncStrategy::AUDIO_MASTER && !m_hasAudio) {
  428. if (m_hasVideo) {
  429. strategy = SyncStrategy::VIDEO_MASTER;
  430. } else {
  431. strategy = SyncStrategy::EXTERNAL_MASTER;
  432. }
  433. } else if (strategy == SyncStrategy::VIDEO_MASTER && !m_hasVideo) {
  434. if (m_hasAudio) {
  435. strategy = SyncStrategy::AUDIO_MASTER;
  436. } else {
  437. strategy = SyncStrategy::EXTERNAL_MASTER;
  438. }
  439. }
  440. m_syncStrategy = strategy;
  441. m_config.strategy = strategy;
  442. }
  443. // 获取同步策略
  444. SyncStrategy SynchronizerV2::getSyncStrategy() const {
  445. return m_syncStrategy;
  446. }
  447. // 设置播放速度
  448. void SynchronizerV2::setPlaybackSpeed(double speed) {
  449. // 限制速度范围
  450. speed = std::max(m_config.clockSpeedMin, std::min(speed, m_config.clockSpeedMax));
  451. // 如果速度没有变化,则不需要更新
  452. if (std::fabs(speed - m_playbackSpeed) < 0.01) {
  453. return;
  454. }
  455. // 更新播放速度
  456. m_playbackSpeed = speed;
  457. // 更新所有时钟的速度
  458. setClockSpeed(ClockType::AUDIO, speed);
  459. setClockSpeed(ClockType::VIDEO, speed);
  460. setClockSpeed(ClockType::EXTERNAL, speed);
  461. // 更新统计信息
  462. std::lock_guard<std::mutex> lock(m_statsMutex);
  463. m_stats.playbackSpeed = speed;
  464. }
  465. // 获取播放速度
  466. double SynchronizerV2::getPlaybackSpeed() const {
  467. return m_playbackSpeed;
  468. }
  469. // 获取统计信息
  470. SyncStatsV2 SynchronizerV2::getStats() const {
  471. std::lock_guard<std::mutex> lock(m_statsMutex);
  472. return m_stats;
  473. }
  474. // 设置同步错误回调
  475. void SynchronizerV2::setSyncErrorCallback(const SyncErrorCallback& callback) {
  476. std::lock_guard<std::mutex> lock(m_callbackMutex);
  477. m_syncErrorCallback = callback;
  478. }
  479. // 设置帧丢弃回调
  480. void SynchronizerV2::setFrameDropCallback(const FrameDropCallback& callback) {
  481. std::lock_guard<std::mutex> lock(m_callbackMutex);
  482. m_frameDropCallback = callback;
  483. }
  484. // 获取调试信息
  485. std::string SynchronizerV2::getDebugInfo() const {
  486. std::stringstream ss;
  487. ss.precision(4);
  488. // 获取当前状态
  489. bool initialized = m_initialized;
  490. bool running = m_running;
  491. bool paused = m_paused;
  492. // 获取时钟值
  493. double audioClock = getClock(ClockType::AUDIO);
  494. double videoClock = getClock(ClockType::VIDEO);
  495. double externalClock = getClock(ClockType::EXTERNAL);
  496. double masterClock = getMasterClock();
  497. // 获取同步策略
  498. SyncStrategy strategy = getSyncStrategy();
  499. std::string strategyStr;
  500. switch (strategy) {
  501. case SyncStrategy::AUDIO_MASTER:
  502. strategyStr = "AUDIO_MASTER";
  503. break;
  504. case SyncStrategy::VIDEO_MASTER:
  505. strategyStr = "VIDEO_MASTER";
  506. break;
  507. case SyncStrategy::EXTERNAL_MASTER:
  508. strategyStr = "EXTERNAL_MASTER";
  509. break;
  510. }
  511. // 获取主时钟类型
  512. ClockType masterType = getMasterClockType();
  513. std::string masterTypeStr;
  514. switch (masterType) {
  515. case ClockType::AUDIO:
  516. masterTypeStr = "AUDIO";
  517. break;
  518. case ClockType::VIDEO:
  519. masterTypeStr = "VIDEO";
  520. break;
  521. case ClockType::EXTERNAL:
  522. masterTypeStr = "EXTERNAL";
  523. break;
  524. }
  525. // 获取统计信息
  526. SyncStatsV2 stats = getStats();
  527. // 构建调试信息
  528. ss << "SynchronizerV2 Debug Info:\n";
  529. ss << " State: " << (initialized ? "Initialized" : "Not Initialized")
  530. << ", " << (running ? "Running" : "Stopped")
  531. << ", " << (paused ? "Paused" : "Playing") << "\n";
  532. ss << " Streams: " << (m_hasAudio ? "Audio" : "No Audio")
  533. << ", " << (m_hasVideo ? "Video" : "No Video") << "\n";
  534. ss << " Sync Strategy: " << strategyStr << "\n";
  535. ss << " CurrentTime: " << getCurrentTime() << "\n";
  536. ss << " Master Clock Type: " << masterTypeStr << "\n";
  537. ss << " Clocks (seconds):\n";
  538. ss << " Audio: " << audioClock << "\n";
  539. ss << " Video: " << videoClock << "\n";
  540. ss << " External: " << externalClock << "\n";
  541. ss << " Master: " << masterClock << "\n";
  542. ss << " Playback Speed: " << m_playbackSpeed << "\n";
  543. ss << " Stats:\n";
  544. ss << " Audio-Video Sync Error: " << stats.audioVideoSyncError << " seconds\n";
  545. ss << " Avg Sync Error: " << stats.avgSyncError << " seconds\n";
  546. ss << " Max Sync Error: " << stats.maxSyncError << " seconds\n";
  547. ss << " Dropped Frames: " << stats.droppedFrames << "\n";
  548. ss << " Duplicated Frames: " << stats.duplicatedFrames << "\n";
  549. return ss.str();
  550. }
  551. // 初始化时钟
  552. void SynchronizerV2::initClock(Clock& clock, int serial) {
  553. clock.pts = 0.0;
  554. clock.ptsDrift = 0.0;
  555. clock.lastUpdated = getCurrentTime();
  556. clock.speed = m_playbackSpeed;
  557. clock.serial = serial;
  558. clock.paused = false;
  559. clock.queueSerial = serial;
  560. }
  561. // 将时钟同步到从属时钟
  562. void SynchronizerV2::syncClockToSlave(Clock& c, const Clock& slave) {
  563. double clockDiff = getClock(ClockType::EXTERNAL) - getClock(ClockType::AUDIO);
  564. double correction = 0.0;
  565. // 根据差异调整时钟速度
  566. if (std::fabs(clockDiff) < m_config.noSyncThreshold) {
  567. if (clockDiff <= -m_config.syncThresholdMin) {
  568. // 外部时钟落后,加速
  569. correction = -m_config.clockSpeedStep;
  570. } else if (clockDiff >= m_config.syncThresholdMin) {
  571. // 外部时钟超前,减速
  572. correction = m_config.clockSpeedStep;
  573. }
  574. // 应用速度调整
  575. c.speed = m_playbackSpeed + correction;
  576. c.speed = std::max(m_config.clockSpeedMin, std::min(c.speed, m_config.clockSpeedMax));
  577. }
  578. }
  579. // 更新外部时钟
  580. void SynchronizerV2::updateExternalClock() {
  581. // 更新外部时钟,使其与主时钟同步
  582. if (getMasterClockType() != ClockType::EXTERNAL) {
  583. double masterClock = getMasterClock();
  584. setClock(ClockType::EXTERNAL, masterClock, m_externalSerial);
  585. }
  586. }
  587. // 检查外部时钟速度
  588. void SynchronizerV2::checkExternalClockSpeed() {
  589. if (m_hasAudio && getMasterClockType() == ClockType::EXTERNAL) {
  590. // 将外部时钟同步到音频时钟
  591. syncClockToSlave(m_externalClock, m_audioClock);
  592. } else if (m_hasVideo && getMasterClockType() == ClockType::EXTERNAL) {
  593. // 将外部时钟同步到视频时钟
  594. syncClockToSlave(m_externalClock, m_videoClock);
  595. }
  596. }
  597. // 获取当前时间(秒)
  598. double SynchronizerV2::getCurrentTime() const
  599. {
  600. return av_gettime_relative() / 1000000.0;
  601. }
  602. // 更新统计信息
  603. void SynchronizerV2::updateStats() {
  604. std::lock_guard<std::mutex> lock(m_statsMutex);
  605. // 更新时钟值
  606. m_stats.audioClock = getClock(ClockType::AUDIO);
  607. m_stats.videoClock = getClock(ClockType::VIDEO);
  608. m_stats.externalClock = getClock(ClockType::EXTERNAL);
  609. m_stats.masterClock = getMasterClock();
  610. // 计算音视频同步误差
  611. if (m_hasAudio && m_hasVideo) {
  612. m_stats.audioVideoSyncError = m_stats.audioClock - m_stats.videoClock;
  613. // 更新平均同步误差
  614. double absError = std::fabs(m_stats.audioVideoSyncError);
  615. m_stats.avgSyncError = (m_stats.avgSyncError * 0.9) + (absError * 0.1);
  616. // 更新最大同步误差
  617. if (absError > m_stats.maxSyncError) {
  618. m_stats.maxSyncError = absError;
  619. }
  620. }
  621. // 更新播放速度
  622. m_stats.playbackSpeed = m_playbackSpeed;
  623. }
  624. // 通知同步错误
  625. void SynchronizerV2::notifySyncError(double error, const std::string& reason) const {
  626. std::lock_guard<std::mutex> lock(m_callbackMutex);
  627. if (m_syncErrorCallback) {
  628. m_syncErrorCallback(error, reason);
  629. }
  630. }
  631. // 通知帧丢弃
  632. void SynchronizerV2::notifyFrameDrop(ClockType type, int64_t pts) const {
  633. std::lock_guard<std::mutex> lock(m_callbackMutex);
  634. if (m_frameDropCallback) {
  635. m_frameDropCallback(type, pts);
  636. }
  637. // 更新统计信息
  638. std::lock_guard<std::mutex> statsLock(m_statsMutex);
  639. m_stats.droppedFrames++;
  640. }
  641. } // namespace utils
  642. } // namespace av