From 80a40ac5f9601d3bd613635ab0e0e1d245bbf165 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Fri, 15 Feb 2019 23:51:20 -0800 Subject: [PATCH] Increase frame drop threshold --- .../video/ffmpeg-renderers/pacer/pacer.cpp | 40 ++++++++++++++----- .../video/ffmpeg-renderers/pacer/pacer.h | 1 + 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/app/streaming/video/ffmpeg-renderers/pacer/pacer.cpp b/app/streaming/video/ffmpeg-renderers/pacer/pacer.cpp index 653ad28c..27d80633 100644 --- a/app/streaming/video/ffmpeg-renderers/pacer/pacer.cpp +++ b/app/streaming/video/ffmpeg-renderers/pacer/pacer.cpp @@ -14,8 +14,6 @@ #include "dxvsyncsource.h" #endif -#define PACING_HISTORY_ENTRIES 8 - // We may be woken up slightly late so don't go all the way // up to the next V-sync since we may accidentally step into // the next V-sync period. It also takes some amount of time @@ -135,7 +133,8 @@ void Pacer::vsyncCallback(int timeUntilNextVsyncMillis) } } - if (m_PacingQueueHistory.count() == PACING_HISTORY_ENTRIES) { + // Keep a rolling 500 ms window of pacing queue history + if (m_PacingQueueHistory.count() == m_DisplayFps / 2) { m_PacingQueueHistory.dequeue(); } @@ -220,19 +219,38 @@ void Pacer::renderFrame(AVFrame* frame) m_VideoStats->renderedFrames++; av_frame_free(&frame); - // If a frame has arrived while rendering, our renderer probably - // was blocked waiting on V-Sync. Drop a frame to allow the - // queued frame to drain. + // Drop frames if we have too many queued up for a while m_FrameQueueLock.lock(); - if (!m_RenderQueue.isEmpty()) { - frame = m_RenderQueue.dequeue(); + + int frameDropTarget = 0; + for (int queueHistoryEntry : m_RenderQueueHistory) { + if (queueHistoryEntry == 0) { + // Be lenient as long as the queue length + // resolves before the end of frame history + frameDropTarget = 2; + break; + } + } + + // Keep a rolling 500 ms window of render queue history + if (m_RenderQueueHistory.count() == m_MaxVideoFps / 2) { + m_RenderQueueHistory.dequeue(); + } + + m_RenderQueueHistory.enqueue(m_RenderQueue.count()); + + // Catch up if we're several frames ahead + while (m_RenderQueue.count() > frameDropTarget) { + AVFrame* frame = m_RenderQueue.dequeue(); + + // Drop the lock while we call av_frame_free() m_FrameQueueLock.unlock(); m_VideoStats->pacerDroppedFrames++; av_frame_free(&frame); + m_FrameQueueLock.lock(); } - else { - m_FrameQueueLock.unlock(); - } + + m_FrameQueueLock.unlock(); } void Pacer::submitFrame(AVFrame* frame) diff --git a/app/streaming/video/ffmpeg-renderers/pacer/pacer.h b/app/streaming/video/ffmpeg-renderers/pacer/pacer.h index 4a7a7203..20bab6f9 100644 --- a/app/streaming/video/ffmpeg-renderers/pacer/pacer.h +++ b/app/streaming/video/ffmpeg-renderers/pacer/pacer.h @@ -34,6 +34,7 @@ private: QQueue m_RenderQueue; QQueue m_PacingQueue; QQueue m_PacingQueueHistory; + QQueue m_RenderQueueHistory; QMutex m_FrameQueueLock; QWaitCondition m_RenderQueueNotEmpty; QWaitCondition m_PacingQueueNotEmpty;