diff --git a/app/streaming/video/ffmpeg-renderers/pacer/pacer.cpp b/app/streaming/video/ffmpeg-renderers/pacer/pacer.cpp index 27d80633..39aa472c 100644 --- a/app/streaming/video/ffmpeg-renderers/pacer/pacer.cpp +++ b/app/streaming/video/ffmpeg-renderers/pacer/pacer.cpp @@ -14,6 +14,10 @@ #include "dxvsyncsource.h" #endif +// Limit the number of queued frames to prevent excessive memory consumption +// if the V-Sync source or renderer is blocked for a while. +#define MAX_QUEUED_FRAMES 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 @@ -162,6 +166,7 @@ void Pacer::vsyncCallback(int timeUntilNextVsyncMillis) } // Place the first frame on the render queue + dropFrameForEnqueue(m_RenderQueue); m_RenderQueue.enqueue(m_PacingQueue.dequeue()); m_FrameQueueLock.unlock(); m_RenderQueueNotEmpty.wakeOne(); @@ -253,6 +258,15 @@ void Pacer::renderFrame(AVFrame* frame) m_FrameQueueLock.unlock(); } +void Pacer::dropFrameForEnqueue(QQueue& queue) +{ + SDL_assert(queue.size() <= MAX_QUEUED_FRAMES); + if (queue.size() == MAX_QUEUED_FRAMES) { + AVFrame* frame = queue.dequeue(); + av_frame_free(&frame); + } +} + void Pacer::submitFrame(AVFrame* frame) { // Make sure initialize() has been called @@ -261,9 +275,11 @@ void Pacer::submitFrame(AVFrame* frame) // Queue the frame and possibly wake up the render thread m_FrameQueueLock.lock(); if (m_VsyncSource != nullptr) { + dropFrameForEnqueue(m_PacingQueue); m_PacingQueue.enqueue(frame); } else { + dropFrameForEnqueue(m_RenderQueue); m_RenderQueue.enqueue(frame); } m_FrameQueueLock.unlock(); diff --git a/app/streaming/video/ffmpeg-renderers/pacer/pacer.h b/app/streaming/video/ffmpeg-renderers/pacer/pacer.h index 20bab6f9..5fd4e720 100644 --- a/app/streaming/video/ffmpeg-renderers/pacer/pacer.h +++ b/app/streaming/video/ffmpeg-renderers/pacer/pacer.h @@ -31,6 +31,8 @@ private: void renderFrame(AVFrame* frame); + void dropFrameForEnqueue(QQueue& queue); + QQueue m_RenderQueue; QQueue m_PacingQueue; QQueue m_PacingQueueHistory;