mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2025-07-18 10:32:38 +00:00
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:
parent
0733f06103
commit
f8f5e8e869
@ -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)
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user