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.
This commit is contained in:
Cameron Gutman 2022-04-24 17:04:32 -05:00
parent 0733f06103
commit f8f5e8e869
2 changed files with 8 additions and 34 deletions

View File

@ -72,8 +72,10 @@ void Pacer::renderOnMainThread()
m_FrameQueueLock.lock(); m_FrameQueueLock.lock();
if (!m_RenderQueue.isEmpty()) { if (!m_RenderQueue.isEmpty()) {
// Releases m_FrameQueueLock AVFrame* frame = m_RenderQueue.dequeue();
renderLastFrameAndUnlock(); m_FrameQueueLock.unlock();
renderFrame(frame);
} }
else { else {
m_FrameQueueLock.unlock(); m_FrameQueueLock.unlock();
@ -109,9 +111,10 @@ int Pacer::renderThread(void* context)
break; break;
} }
// Render the latest frame and discard the others AVFrame* frame = me->m_RenderQueue.dequeue();
// NB: m_FrameQueueLock still held here! me->m_FrameQueueLock.unlock();
me->renderLastFrameAndUnlock();
me->renderFrame(frame);
} }
// Notify the renderer that it is being destroyed soon // 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 // Called in an arbitrary thread by the IVsyncSource on V-sync
// or an event synchronized with V-sync // or an event synchronized with V-sync
void Pacer::vsyncCallback(int timeUntilNextVsyncMillis) void Pacer::vsyncCallback(int timeUntilNextVsyncMillis)

View File

@ -33,8 +33,6 @@ private:
void enqueueFrameForRenderingAndUnlock(AVFrame* frame); void enqueueFrameForRenderingAndUnlock(AVFrame* frame);
void renderLastFrameAndUnlock();
void renderFrame(AVFrame* frame); void renderFrame(AVFrame* frame);
void dropFrameForEnqueue(QQueue<AVFrame*>& queue); void dropFrameForEnqueue(QQueue<AVFrame*>& queue);