utils_synchronizer_v2.cpp 22 KB

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