mirror of
https://github.com/moonlight-stream/moonlight-qt.git
synced 2025-07-18 10:32:38 +00:00
Let Pacer know what the display Hz and stream FPS are so it can make better drop decisions
This commit is contained in:
parent
f171588616
commit
f929cffce7
@ -3,7 +3,9 @@
|
|||||||
#define FRAME_HISTORY_ENTRIES 8
|
#define FRAME_HISTORY_ENTRIES 8
|
||||||
|
|
||||||
Pacer::Pacer() :
|
Pacer::Pacer() :
|
||||||
m_FrameQueueLock(0)
|
m_FrameQueueLock(0),
|
||||||
|
m_MaxVideoFps(0),
|
||||||
|
m_DisplayFps(0)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -13,28 +15,60 @@ Pacer::~Pacer()
|
|||||||
drain();
|
drain();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Pacer::initialize(SDL_Window* window, int maxVideoFps)
|
||||||
|
{
|
||||||
|
m_MaxVideoFps = maxVideoFps;
|
||||||
|
|
||||||
|
int displayIndex = SDL_GetWindowDisplayIndex(window);
|
||||||
|
if (displayIndex < 0) {
|
||||||
|
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"Failed to get current display: %s",
|
||||||
|
SDL_GetError());
|
||||||
|
|
||||||
|
// Assume display 0 if it fails
|
||||||
|
displayIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_DisplayMode mode;
|
||||||
|
if (SDL_GetCurrentDisplayMode(displayIndex, &mode) == 0) {
|
||||||
|
// May be zero if undefined
|
||||||
|
m_DisplayFps = mode.refresh_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
"Frame pacing: target %d Hz with %d FPS stream",
|
||||||
|
m_DisplayFps, m_MaxVideoFps);
|
||||||
|
}
|
||||||
|
|
||||||
AVFrame* Pacer::getFrameAtVsync()
|
AVFrame* Pacer::getFrameAtVsync()
|
||||||
{
|
{
|
||||||
SDL_AtomicLock(&m_FrameQueueLock);
|
// Make sure initialize() has been called
|
||||||
|
SDL_assert(m_MaxVideoFps != 0);
|
||||||
|
|
||||||
int frameDropTarget;
|
SDL_AtomicLock(&m_FrameQueueLock);
|
||||||
|
|
||||||
// If the queue length history entries are large, be strict
|
// If the queue length history entries are large, be strict
|
||||||
// about dropping excess frames.
|
// about dropping excess frames.
|
||||||
frameDropTarget = 1;
|
int frameDropTarget = 1;
|
||||||
for (int i = 0; i < m_FrameQueueHistory.count(); i++) {
|
|
||||||
if (m_FrameQueueHistory[i] <= 1) {
|
// If we may get more frames per second than we can display, use
|
||||||
// Be lenient as long as the queue length
|
// frame history to drop frames only if consistently above the
|
||||||
// resolves before the end of frame history
|
// one queued frame mark.
|
||||||
frameDropTarget = 3;
|
if (m_MaxVideoFps >= m_DisplayFps) {
|
||||||
|
for (int i = 0; i < m_FrameQueueHistory.count(); i++) {
|
||||||
|
if (m_FrameQueueHistory[i] <= 1) {
|
||||||
|
// Be lenient as long as the queue length
|
||||||
|
// resolves before the end of frame history
|
||||||
|
frameDropTarget = 3;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (m_FrameQueueHistory.count() == FRAME_HISTORY_ENTRIES) {
|
if (m_FrameQueueHistory.count() == FRAME_HISTORY_ENTRIES) {
|
||||||
m_FrameQueueHistory.dequeue();
|
m_FrameQueueHistory.dequeue();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_FrameQueueHistory.enqueue(m_FrameQueue.count());
|
m_FrameQueueHistory.enqueue(m_FrameQueue.count());
|
||||||
|
}
|
||||||
|
|
||||||
// Catch up if we're several frames ahead
|
// Catch up if we're several frames ahead
|
||||||
while (m_FrameQueue.count() > frameDropTarget) {
|
while (m_FrameQueue.count() > frameDropTarget) {
|
||||||
@ -56,6 +90,9 @@ AVFrame* Pacer::getFrameAtVsync()
|
|||||||
|
|
||||||
void Pacer::submitFrame(AVFrame* frame)
|
void Pacer::submitFrame(AVFrame* frame)
|
||||||
{
|
{
|
||||||
|
// Make sure initialize() has been called
|
||||||
|
SDL_assert(m_MaxVideoFps != 0);
|
||||||
|
|
||||||
SDL_AtomicLock(&m_FrameQueueLock);
|
SDL_AtomicLock(&m_FrameQueueLock);
|
||||||
m_FrameQueue.enqueue(frame);
|
m_FrameQueue.enqueue(frame);
|
||||||
SDL_AtomicUnlock(&m_FrameQueueLock);
|
SDL_AtomicUnlock(&m_FrameQueueLock);
|
||||||
|
@ -15,10 +15,15 @@ public:
|
|||||||
|
|
||||||
void submitFrame(AVFrame* frame);
|
void submitFrame(AVFrame* frame);
|
||||||
|
|
||||||
|
void initialize(SDL_Window* window, int maxVideoFps);
|
||||||
|
|
||||||
void drain();
|
void drain();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QQueue<AVFrame*> m_FrameQueue;
|
QQueue<AVFrame*> m_FrameQueue;
|
||||||
QQueue<int> m_FrameQueueHistory;
|
QQueue<int> m_FrameQueueHistory;
|
||||||
SDL_SpinLock m_FrameQueueLock;
|
SDL_SpinLock m_FrameQueueLock;
|
||||||
|
|
||||||
|
int m_MaxVideoFps;
|
||||||
|
int m_DisplayFps;
|
||||||
};
|
};
|
||||||
|
@ -131,10 +131,12 @@ public:
|
|||||||
int videoFormat,
|
int videoFormat,
|
||||||
int,
|
int,
|
||||||
int,
|
int,
|
||||||
int) override
|
int maxFps) override
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
m_Pacer.initialize(window, maxFps);
|
||||||
|
|
||||||
if (videoFormat & VIDEO_FORMAT_MASK_H264) {
|
if (videoFormat & VIDEO_FORMAT_MASK_H264) {
|
||||||
// Prior to 10.13, we'll just assume everything has
|
// Prior to 10.13, we'll just assume everything has
|
||||||
// H.264 support and fail open to allow VT decode.
|
// H.264 support and fail open to allow VT decode.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user