Better frame sheduling for smoothness

This commit is contained in:
Niellune
2026-03-27 23:41:40 +02:00
parent 79965af3e6
commit 74f039e36f
6 changed files with 45 additions and 49 deletions
+10 -2
View File
@@ -31,9 +31,17 @@ debug: LDFLAGS += -fsanitize=address -fno-omit-frame-pointer
debug: TARGET := $(TARGET_NAME)-debug
debug: prepare
ifeq ($(shell uname -s), Darwin)
# macOS / clang
PLATFORM_LDFLAGS :=
else
# Linux / GCC (Pi or other)
PLATFORM_LDFLAGS := -Wl,--gc-sections -Wl,--as-needed
endif
release: BUILD_TYPE := release
release: CXXFLAGS := -O3 -ffast-math -march=native -fno-plt -fno-rtti -flto -fdata-sections -ffunction-sections -DNDEBUG
release: LDFLAGS += -O3 -ffast-math -march=native -Wl,--gc-sections -flto
release: CXXFLAGS := -O2 -ffast-math -march=native -fno-plt -fno-rtti -flto -fdata-sections -ffunction-sections -ffunction-sections -fomit-frame-pointer -fvisibility=hidden -pipe -DNDEBUG
release: LDFLAGS += -O2 -ffast-math -march=native -flto -Wl,-O1 $(PLATFORM_LDFLAGS)
release: TARGET := $(TARGET_NAME)
release: prepare
-6
View File
@@ -14,12 +14,6 @@
# Requested image refresh rate
#source-fps = 60
# Application drawing target framerate. This can responsiveness.
# If the setting is lower than source-fps the framse will be dropped
# If the setting is not multiple of source-fps can still cause frame drops cause out-of-sync
# source images and drawing times
#fps = 60
# Application window mode
# 0 - windowed
# 1 - fullscreen
+30 -38
View File
@@ -3,6 +3,8 @@
#include <SDL2/SDL_ttf.h>
#include <cstdio>
#include <sstream>
#include <chrono>
#include <thread>
#include "struct/video_buffer.h"
#include "common/logger.h"
@@ -313,21 +315,20 @@ void Application::loop()
protocol.start();
log_v("Loop");
Uint32 frameStart = SDL_GetTicks();
std::chrono::steady_clock::time_point frameStart = std::chrono::steady_clock::now();
int32_t frameTime = 0;
int32_t frameDelay = 0;
const int32_t frameTarget = Settings::sourceFps > 0 ? 1000000 / Settings::sourceFps : 1000000;
AVFrame *frame = nullptr;
uint32_t frameid = 0;
uint32_t latestFrameid = 0;
uint32_t frameTargetTime = Settings::fps > 0 ? 1000 / Settings::fps : 1000;
uint32_t delay = 0;
uint32_t frameId = 0;
uint32_t dropframes = 0;
int skipEvents = 0;
int frameTime = 0;
Uint32 debugLast = SDL_GetTicks();
int debugSpeed = 0;
int debugLastCount = 0;
while (_active)
{
bool late = false;
bool newFrame = false;
if (protocol.state() != _state.latestState)
{
@@ -347,29 +348,24 @@ void Application::loop()
_state.latestState = protocol.state();
}
if (_state.latestState == PROTOCOL_STATUS_CONNECTED && _state.showVideo)
if (_state.latestState == PROTOCOL_STATUS_CONNECTED)
{
delay = 0;
while (!_state.dirty && decoder.buffer.latestId() == latestFrameid && ++delay < frameTargetTime)
uint32_t latestFrameId = 0;
if (decoder.buffer.consume(&frame, &latestFrameId))
{
SDL_Delay(1);
}
if (decoder.buffer.consume(&frame, &frameid))
{
bool newFrame = frameid != latestFrameid;
newFrame = latestFrameId != frameId;
if (newFrame || _state.dirty)
{
if (interface.render(frame))
{
_state.frameRendered = true;
_state.dirty = false;
if (latestFrameid > 0 && frameid - latestFrameid > 1)
if (frameId > 0 && latestFrameId - frameId > 1)
{
dropframes += frameid - latestFrameid - 1;
log_d("Frame drop %d on %d total %d", frameid - latestFrameid - 1, frameid, dropframes);
dropframes += latestFrameId - frameId - 1;
log_d("Frame drop %d on %d total %d", latestFrameId - frameId - 1, latestFrameId, dropframes);
}
latestFrameid = frameid;
frameId = latestFrameId;
}
}
}
@@ -383,7 +379,7 @@ void Application::loop()
}
}
if (!_state.frameRendered || !_state.showVideo)
if (!_state.frameRendered)
{
interface.drawHome(_state.dirty, _state.latestState, protocol.phoneName());
_state.dirty = false;
@@ -393,8 +389,7 @@ void Application::loop()
}
else
{
late = decoder.buffer.latestId() - latestFrameid > 1;
if (!late || ++skipEvents > Settings::eventsSkip)
if (newFrame || ++skipEvents > Settings::eventsSkip)
{
if (processFrameEvents(protocol.writeQueue, interface) && Settings::forceRedraw > 0)
{
@@ -415,16 +410,16 @@ void Application::loop()
char debugBuffer[2048];
std::snprintf(debugBuffer, sizeof(debugBuffer),
"%s\n"
"FRAME: %u / %u [%d] dropped: %d render: %dms / %dms\n"
"FRAME: %u / %u [%d] dropped: %d render: %uus / %uus\n"
"USB: %s ~%dKB/s\n"
"BUFF: video [%u] audio[main %u aux %u] out [%u]",
status().c_str(),
latestFrameid,
frameId,
decoder.buffer.latestId(),
decoder.buffer.latestId() - latestFrameid,
decoder.buffer.latestId() - frameId,
dropframes,
frameTime,
delay,
frameDelay,
protocol.status().c_str(),
debugSpeed,
protocol.videoStream.count(),
@@ -434,19 +429,16 @@ void Application::loop()
interface.debug(debugBuffer);
}
if (_active && !Settings::vsync)
if (_active && !Settings::vsync && !_state.dirty)
{
Uint32 frameEnd = SDL_GetTicks();
frameTime = frameEnd - frameStart;
int frameDelay = frameTargetTime - frameTime;
if (frameDelay <= 0 || decoder.buffer.latestId() - latestFrameid > 1)
std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
frameTime = (int32_t)std::chrono::duration_cast<std::chrono::microseconds>(now - frameStart).count();
frameDelay = (frameTarget - frameTime) * ((decoder.buffer.latestId() == frameId) ? 1.0 : 0.9);
frameStart = now;
if (frameDelay > 0)
{
frameStart = frameEnd;
}
else
{
SDL_Delay(frameDelay);
frameStart += frameDelay;
std::this_thread::sleep_for(std::chrono::microseconds(frameDelay));
frameStart += std::chrono::microseconds(frameDelay);
}
}
}
-1
View File
@@ -24,7 +24,6 @@ private:
bool dirty = false;
bool frameRendered = false;
int requestFrame = 0;
bool showVideo = true;
bool fullscreen = false;
bool mouseDown = false;
int8_t latestState = PROTOCOL_STATUS_UNKNOWN;
+5 -1
View File
@@ -77,8 +77,12 @@ bool Interface::drawHome(bool force, int state, std::string name)
drawText = true;
if (state == PROTOCOL_STATUS_CONNECTED)
if (_textStatus.prepare(_renderer, "Connecting to "+name, color3))
{
if(name.length()>0)
name = " to "+name;
if (_textStatus.prepare(_renderer, "Connecting"+name, color3))
drawText = true;
}
if (drawText)
_textStatus.draw(_renderer, (width - _textStatus.width) / 2, height * 0.85 - _textStatus.height);
-1
View File
@@ -17,7 +17,6 @@ public:
static inline Setting<int> width{"width", 1024};
static inline Setting<int> height{"height", 576};
static inline Setting<int> sourceFps{"source-fps", 60};
static inline Setting<int> fps{"fps", 60};
static inline Setting<int> screenMode{"window-mode", 0};
static inline Setting<bool> cursor{"cursor", false};
static inline Setting<int> loglevel{"log-level", 2};