From f8f5e8e86967f7387726e9768c702ac1fd7e6f76 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 24 Apr 2022 17:04:32 -0500 Subject: [PATCH] Don't discard all excess frames before rendering This prevents the render queue's pacing logic from working and interferes with renderers that take a full v-sync period between their waitToRender() and renderFrame() callbacks. --- .../video/ffmpeg-renderers/pacer/pacer.cpp | 40 ++++--------------- .../video/ffmpeg-renderers/pacer/pacer.h | 2 - 2 files changed, 8 insertions(+), 34 deletions(-) diff --git a/app/streaming/video/ffmpeg-renderers/pacer/pacer.cpp b/app/streaming/video/ffmpeg-renderers/pacer/pacer.cpp index 52c8ce87..84b247bd 100644 --- a/app/streaming/video/ffmpeg-renderers/pacer/pacer.cpp +++ b/app/streaming/video/ffmpeg-renderers/pacer/pacer.cpp @@ -72,8 +72,10 @@ void Pacer::renderOnMainThread() m_FrameQueueLock.lock(); if (!m_RenderQueue.isEmpty()) { - // Releases m_FrameQueueLock - renderLastFrameAndUnlock(); + AVFrame* frame = m_RenderQueue.dequeue(); + m_FrameQueueLock.unlock(); + + renderFrame(frame); } else { m_FrameQueueLock.unlock(); @@ -109,9 +111,10 @@ int Pacer::renderThread(void* context) break; } - // Render the latest frame and discard the others - // NB: m_FrameQueueLock still held here! - me->renderLastFrameAndUnlock(); + AVFrame* frame = me->m_RenderQueue.dequeue(); + me->m_FrameQueueLock.unlock(); + + me->renderFrame(frame); } // Notify the renderer that it is being destroyed soon @@ -141,33 +144,6 @@ void Pacer::enqueueFrameForRenderingAndUnlock(AVFrame *frame) } } -// Caller must hold m_FrameQueueLock -void Pacer::renderLastFrameAndUnlock() -{ - // Dequeue the most recent frame for rendering and free the others. - AVFrame* lastFrame = nullptr; - while (!m_RenderQueue.isEmpty()) { - if (lastFrame != nullptr) { - // Don't hold the frame queue lock across av_frame_free(), - // since it could need to talk to the GPU driver. This is safe - // because we're guaranteed that the queue will not shrink during - // this time (and so dequeue() below will always get something). - m_FrameQueueLock.unlock(); - av_frame_free(&lastFrame); - m_VideoStats->pacerDroppedFrames++; - m_FrameQueueLock.lock(); - } - - lastFrame = m_RenderQueue.dequeue(); - } - - // Release the frame queue lock before rendering - m_FrameQueueLock.unlock(); - - // Render and free the mot current frame - renderFrame(lastFrame); -} - // Called in an arbitrary thread by the IVsyncSource on V-sync // or an event synchronized with V-sync void Pacer::vsyncCallback(int timeUntilNextVsyncMillis) diff --git a/app/streaming/video/ffmpeg-renderers/pacer/pacer.h b/app/streaming/video/ffmpeg-renderers/pacer/pacer.h index 6702dbae..ed1c4a39 100644 --- a/app/streaming/video/ffmpeg-renderers/pacer/pacer.h +++ b/app/streaming/video/ffmpeg-renderers/pacer/pacer.h @@ -33,8 +33,6 @@ private: void enqueueFrameForRenderingAndUnlock(AVFrame* frame); - void renderLastFrameAndUnlock(); - void renderFrame(AVFrame* frame); void dropFrameForEnqueue(QQueue& queue);