@@ -190,15 +190,21 @@ void Pacer::updateFrameStats() {
190190
191191// Main render thread
192192
193- void Pacer::waitForFrame (double timeoutMs) {
193+ void Pacer::waitForFrame (double timeoutMs, bool waitFullTime ) {
194194 if (!running ()) return ;
195195
196- // mark frame begin for use by afterPresent
197- m_BeginFrameQpc = QpcNow ();
198-
199196 // Wait for a decoded frame to be available
197+ int64_t t0 = QpcNow ();
200198 int queueHas = 1 ;
201199 FrameQueue::instance ().waitForEnqueue (queueHas, timeoutMs);
200+
201+ if (waitFullTime) {
202+ int64_t t1 = QpcNow ();
203+ timeoutMs -= QpcToMs (t1 - t0);
204+ if (timeoutMs > 0.0 ) {
205+ SleepUntilQpc (t1 + MsToQpc (timeoutMs));
206+ }
207+ }
202208}
203209
204210// called by render thread
@@ -214,7 +220,9 @@ bool Pacer::renderOnMainThread(std::shared_ptr<VideoRenderer> &sceneRenderer) {
214220
215221 // Render it
216222 FQLog (" > Frame rendered [pts: %.3f]\n " , frame->pts / 90.0 );
217- sceneRenderer->Render (frame);
223+ if (!sceneRenderer->Render (frame)) {
224+ return false ; // something went wrong rendering the frame
225+ }
218226
219227 if (frame->opaque_ref ) {
220228 // Count time spent in FrameQueue
@@ -227,26 +235,23 @@ bool Pacer::renderOnMainThread(std::shared_ptr<VideoRenderer> &sceneRenderer) {
227235}
228236
229237// called by render thread
230- void Pacer::waitBeforePresent () {
238+ void Pacer::waitBeforePresent (int64_t deadline = 0 ) {
231239 if (!running ()) return ;
232240
233241 // Wait until vsync
234- int64_t now, interval = 0 ;
235- int64_t target = getNextVBlankQpc (&now, &interval);
236-
237- if (IsXbox () && m_StreamFps == 120 && m_RefreshRate > 119.0 ) {
238- // 120hz on Xbox requires us to present each frame at half-vsync intervals
239- int64_t half = interval / 2 ;
240- if (target - half > now) {
241- // we're currently in the first half of a vblank, sleep till the halfway mark
242- target -= half;
243- }
242+ int64_t now = 0 ;
243+ int64_t target = getNextVBlankQpc (&now);
244+ if (deadline && deadline != target) {
245+ // we missed the deadline
246+ target = deadline;
244247 }
245248
246249 m_LastSyncTarget.store (target, std::memory_order_release);
247250
248- FQLog (" waitBeforePresent(): waiting %.3fms to target %lld\n " , QpcToMs (target - now), target);
249- SleepUntilQpc (target);
251+ if (target > now) {
252+ FQLog (" waitBeforePresent(): waiting %.3fms\n " , QpcToMs (target - now));
253+ SleepUntilQpc (target);
254+ }
250255}
251256
252257// end main thread
@@ -267,23 +272,34 @@ void Pacer::submitFrame(AVFrame *frame) {
267272
268273// Caller often needs now and the vsync interval, since this needs locking
269274// the logic is confined to this function.
270- int64_t Pacer::getNextVBlankQpc (int64_t *now, int64_t *interval ) {
275+ int64_t Pacer::getNextVBlankQpc (int64_t *now) {
271276 std::scoped_lock<std::mutex> lock (m_FrameStatsLock);
277+ int64_t target, interval = 0 ;
278+ *now = QpcNow ();
272279
273280 if (m_LastSyncQpc == 0 || m_VsyncIntervalQpc == 0 ) {
274281 // Fallback until vsyncHardware spins up
275- *now = QpcNow ();
276282 double rr = m_RefreshRate > 0.0 ? m_RefreshRate : 60.0 ;
277- *interval = MsToQpc (1000.0 / rr);
278- return *now + *interval;
279- }
283+ interval = MsToQpc (1000.0 / rr);
284+ target = *now + interval;
285+ } else {
286+ interval = m_VsyncIntervalQpc;
287+ int64_t next = m_LastSyncQpc;
280288
281- *now = QpcNow ();
282- *interval = m_VsyncIntervalQpc;
283- int64_t next = m_LastSyncQpc;
289+ while (next < *now) {
290+ next += interval;
291+ }
292+ target = next + static_cast <int64_t >(m_ewmaVsyncDriftQpc);
293+ }
284294
285- while (next < *now) {
286- next += *interval;
295+ if (IsXbox () && m_StreamFps == 120 && m_RefreshRate > 119.0 ) {
296+ // 120hz on Xbox requires us to present each frame at half-vsync intervals
297+ int64_t half = interval / 2 ;
298+ if (target - half > *now) {
299+ // we're currently in the first half of a vblank, sleep till the halfway mark
300+ target -= half;
301+ }
287302 }
288- return next + static_cast <int64_t >(m_ewmaVsyncDriftQpc);
303+
304+ return target;
289305}
0 commit comments