9 #define LOC QString("AVSync: ")
25 LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO,
LOC +
"Reset");
30 auto unow = std::chrono::microseconds(
m_avTimer.nsecsElapsed() / 1000);
31 auto delay = FrameDue - unow;
33 QThread::usleep(delay.count());
51 Map.insert(
"avsync", QObject::tr(
"%1 ms").arg(
m_avsyncAvg / 1000));
56 std::chrono::microseconds FrameInterval,
float PlaySpeed,
57 bool HaveVideo,
bool Force)
70 LOG(VB_PLAYBACK, LOG_DEBUG,
LOC + QString(
"Dropping short frame"));
76 std::chrono::milliseconds videotimecode = 0ms;
77 bool dropframe =
false;
78 bool pause_audio =
false;
79 std::chrono::microseconds framedue = 0us;
80 std::chrono::milliseconds audio_adjustment = 0ms;
81 std::chrono::microseconds unow = 0ms;
82 std::chrono::microseconds lateness = 0us;
84 auto intervalms = duration_cast<std::chrono::milliseconds>(FrameInterval);
86 static float const s_av_control_gain = 0.4F;
88 static float const s_sync_fc = 0.9F;
93 while (framedue == 0us)
97 videotimecode = std::chrono::milliseconds(
Frame->m_timecode.count() & 0x0000ffffffffffff);
99 if (videotimecode !=
Frame->m_timecode)
103 unow = std::chrono::microseconds(
m_avTimer.nsecsElapsed() / 1000);
107 framedue = unow + FrameInterval;
115 if (videotimecode == 0ms)
119 bool dataonly = !Audio->
HasAudioIn() && !HaveVideo;
123 if (videotimecode == 0ms && !dataonly)
126 m_rtcBase = unow - chronodivide<std::chrono::microseconds>(videotimecode, PlaySpeed);
132 if (videotimecode == 0ms)
134 std::chrono::milliseconds tcincr = videotimecode -
m_maxTcVal;
135 if (tcincr > 0ms || tcincr < -100ms)
146 if (PlaySpeed > 0.0F)
147 framedue =
m_rtcBase + chronodivide<std::chrono::microseconds>(videotimecode, PlaySpeed);
149 framedue = unow + FrameInterval / 2;
151 lateness = unow - framedue;
161 if (audio_adjustment < -200ms
165 audio_adjustment = 0ms;
167 int sign = audio_adjustment < 0ms ? -1 : 1;
168 float fix_amount_ms = (
m_lastFix * s_sync_fc + (1 - s_sync_fc) * audio_adjustment.count()) * sign * s_av_control_gain;
172 if ((audio_adjustment * sign) > intervalms)
174 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Audio %1 by %2 ms")
175 .arg(audio_adjustment > 0ms ?
"ahead" :
"behind").arg(abs(audio_adjustment.count())));
177 if (audio_adjustment > 200ms)
188 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Resetting: lateness %1").arg(lateness.count()));
191 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Resetting: lateness = %1").arg(lateness.count()));
206 || audio_adjustment < 0ms)
224 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"Dropping frame: Video is behind by %1ms")
225 .arg(duration_cast<std::chrono::milliseconds>(lateness).count()));
231 LOG(VB_PLAYBACK | VB_TIMESTAMP, LOG_INFO,
LOC +
232 QString(
"A/V timecodes audio=%1 video=%2 frameinterval=%3 audioadj=%4 unow=%5 udue=%6 ")
234 .arg(audio_adjustment.count()).arg(unow.count()).arg(framedue.count()));