Thread priority, better debug overlay

This commit is contained in:
Niellune
2026-03-24 18:08:01 +02:00
parent 6001a0eb96
commit 929b613ab8
5 changed files with 187 additions and 17 deletions
+65 -6
View File
@@ -2,6 +2,7 @@
#include <SDL2/SDL_ttf.h> #include <SDL2/SDL_ttf.h>
#include <cstdio> #include <cstdio>
#include <sstream>
#include "struct/video_buffer.h" #include "struct/video_buffer.h"
#include "common/logger.h" #include "common/logger.h"
@@ -393,7 +394,7 @@ void Application::loop()
else else
{ {
late = decoder.buffer.latestId() - latestFrameid > 1; late = decoder.buffer.latestId() - latestFrameid > 1;
if(!late || ++skipEvents > Settings::eventsSkip) if (!late || ++skipEvents > Settings::eventsSkip)
{ {
if (processFrameEvents(protocol.writeQueue, interface) && Settings::forceRedraw > 0) if (processFrameEvents(protocol.writeQueue, interface) && Settings::forceRedraw > 0)
{ {
@@ -405,18 +406,21 @@ void Application::loop()
if (_debug) if (_debug)
{ {
char debugBuffer[256]; char debugBuffer[512];
std::snprintf(debugBuffer, sizeof(debugBuffer), std::snprintf(debugBuffer, sizeof(debugBuffer),
"FRAME: %u / %u [%d] droped %d\n" "%s\n"
"TIME: %d delay %d\n" "FRAME: %u / %u [%d] dropped: %d render: %dms / %dms\n"
"VIDEO: %u\n" "VIDEO: %u\n"
"AUDIO-MAIN: %u\n" "AUDIO-MAIN: %u\n"
"AUDIO-AUX: %u\n" "AUDIO-AUX: %u\n"
"OUT: %u", "OUT: %u",
status().c_str(),
latestFrameid, latestFrameid,
decoder.buffer.latestId(), decoder.buffer.latestId(),
decoder.buffer.latestId() - latestFrameid, dropframes, decoder.buffer.latestId() - latestFrameid,
frameTime, delay, dropframes,
frameTime,
delay,
protocol.videoStream.count(), protocol.videoStream.count(),
protocol.audioStreamMain.count(), protocol.audioStreamMain.count(),
protocol.audioStreamAux.count(), protocol.audioStreamAux.count(),
@@ -444,3 +448,58 @@ void Application::loop()
if (!Settings::isHeadless()) if (!Settings::isHeadless())
SDL_HideWindow(_window); SDL_HideWindow(_window);
} }
const std::string Application::status() const
{
std::ostringstream out;
SDL_version compiled{};
SDL_VERSION(&compiled);
SDL_version linked{};
SDL_GetVersion(&linked);
out << "SDL: v"
<< static_cast<int>(compiled.major) << '.'
<< static_cast<int>(compiled.minor) << '.'
<< static_cast<int>(compiled.patch) << " "
<< SDL_GetCurrentVideoDriver();
SDL_Window *window = SDL_GetKeyboardFocus();
if (window)
{
int width = 0;
int height = 0;
SDL_GetWindowSize(window, &width, &height);
out << " " << width << 'x' << height;
SDL_Renderer *renderer = SDL_GetRenderer(window);
if (renderer)
{
SDL_RendererInfo info{};
if (SDL_GetRendererInfo(renderer, &info) == 0)
{
out << " " << info.name
<< ((info.flags & SDL_RENDERER_ACCELERATED) != 0?" accelerated":"")
<< ((info.flags & SDL_RENDERER_PRESENTVSYNC) != 0?" vsync":"");
}
}
}
out << " " << SDL_GetCurrentAudioDriver();
int displayIndex = SDL_GetWindowDisplayIndex(window);
if (displayIndex >= 0)
{
out << "\nSCREEN:";
SDL_Rect bounds{};
SDL_DisplayMode mode{};
SDL_GetDisplayBounds(displayIndex, &bounds);
if (SDL_GetCurrentDisplayMode(displayIndex, &mode) == 0)
{
out << " [" << displayIndex << "] "
<< bounds.w << 'x' << bounds.h
<< '@' << mode.refresh_rate
<< " " << SDL_GetPixelFormatName(mode.format);
}
}
return out.str();
}
+1
View File
@@ -35,6 +35,7 @@ private:
int processKey(SDL_Keysym key); int processKey(SDL_Keysym key);
bool processSystemEvent(const SDL_Event &e); bool processSystemEvent(const SDL_Event &e);
bool processFrameEvents(AtomicQueue<Message> &queue, Renderer &renderer); bool processFrameEvents(AtomicQueue<Message> &queue, Renderer &renderer);
const std::string status() const;
void loop(); void loop();
+100 -9
View File
@@ -1,23 +1,114 @@
#ifndef SRC_HELPER_THREADING #ifndef SRC_HELPER_THREADING
#define SRC_HELPER_THREADING #define SRC_HELPER_THREADING
#include <thread>
#if defined(__linux__) || defined(__APPLE__) #if defined(__linux__) || defined(__APPLE__)
#include <pthread.h> #include <pthread.h>
#endif #endif
extern "C" #if defined(__linux__)
{ #include <sched.h>
#include <libavutil/error.h> #elif defined(_WIN32)
} #include <windows.h>
#endif
inline void setThreadName(const char *name) inline void setThreadName(const char* name)
{ {
#if defined(__linux__) #if defined(__linux__)
pthread_setname_np(pthread_self(), name); // Linux: OK (limit 16 chars including null) pthread_setname_np(pthread_self(), name);
#elif defined(__APPLE__) #elif defined(__APPLE__)
pthread_setname_np(name); // macOS: only current thread, OK pthread_setname_np(name);
#elif defined(_WIN32)
// Windows 10+
using SetThreadDescriptionFunc = HRESULT(WINAPI*)(HANDLE, PCWSTR);
static auto func = (SetThreadDescriptionFunc)
GetProcAddress(GetModuleHandleA("Kernel32.dll"), "SetThreadDescription");
if (func)
{
wchar_t wname[64];
mbstowcs(wname, name, 63);
wname[63] = 0;
func(GetCurrentThread(), wname);
}
#else #else
(void)name; // suppress unused warning (void)name;
#endif
}
enum class ThreadPriority
{
Low,
Normal,
High,
Realtime
};
inline bool setThreadPriority(ThreadPriority prio)
{
#if defined(__linux__)
int policy = SCHED_OTHER;
sched_param param{};
switch (prio)
{
case ThreadPriority::Low:
case ThreadPriority::Normal:
policy = SCHED_OTHER;
param.sched_priority = 0;
break;
case ThreadPriority::High:
policy = SCHED_FIFO;
param.sched_priority = 10;
break;
case ThreadPriority::Realtime:
policy = SCHED_FIFO;
param.sched_priority = 50;
break;
}
return pthread_setschedparam(pthread_self(), policy, &param) == 0;
#elif defined(__APPLE__)
qos_class_t qos = QOS_CLASS_DEFAULT;
switch (prio)
{
case ThreadPriority::Low: qos = QOS_CLASS_BACKGROUND; break;
case ThreadPriority::Normal: qos = QOS_CLASS_DEFAULT; break;
case ThreadPriority::High: qos = QOS_CLASS_USER_INITIATED; break;
case ThreadPriority::Realtime: qos = QOS_CLASS_USER_INTERACTIVE; break;
}
return pthread_set_qos_class_self_np(qos, 0) == 0;
#elif defined(_WIN32)
int winPrio = THREAD_PRIORITY_NORMAL;
switch (prio)
{
case ThreadPriority::Low: winPrio = THREAD_PRIORITY_BELOW_NORMAL; break;
case ThreadPriority::Normal: winPrio = THREAD_PRIORITY_NORMAL; break;
case ThreadPriority::High: winPrio = THREAD_PRIORITY_ABOVE_NORMAL; break;
case ThreadPriority::Realtime: winPrio = THREAD_PRIORITY_TIME_CRITICAL; break;
}
return SetThreadPriority(GetCurrentThread(), winPrio);
#else
(void)prio;
return false;
#endif #endif
} }
+20 -2
View File
@@ -24,7 +24,7 @@ Interface::~Interface()
bool Interface::render(AVFrame *frame) bool Interface::render(AVFrame *frame)
{ {
if(!frame) if (!frame)
return false; return false;
if (_render == nullptr || frame->width != _textureWidth || frame->height != _textureHeight) if (_render == nullptr || frame->width != _textureWidth || frame->height != _textureHeight)
@@ -91,7 +91,14 @@ void Interface::drawDebug()
constexpr int padding = 8; constexpr int padding = 8;
constexpr int lineSpacing = 2; constexpr int lineSpacing = 2;
const SDL_Color debugColor = {255, 0, 255, 255}; const SDL_Color debugColor = {0, 255, 255, 255};
SDL_BlendMode previousBlendMode;
Uint8 previousR, previousG, previousB, previousA;
SDL_GetRenderDrawBlendMode(_renderer, &previousBlendMode);
SDL_GetRenderDrawColor(_renderer, &previousR, &previousG, &previousB, &previousA);
SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_BLEND);
SDL_SetRenderDrawColor(_renderer, 0, 0, 0, 150);
size_t lineStart = 0; size_t lineStart = 0;
int y = padding; int y = padding;
@@ -100,7 +107,15 @@ void Interface::drawDebug()
size_t lineEnd = _debugText.find('\n', lineStart); size_t lineEnd = _debugText.find('\n', lineStart);
std::string line = _debugText.substr(lineStart, lineEnd - lineStart); std::string line = _debugText.substr(lineStart, lineEnd - lineStart);
if (_textDebug.prepare(_renderer, line, debugColor)) if (_textDebug.prepare(_renderer, line, debugColor))
{
SDL_Rect backgroundRect = {
0,
y,
static_cast<int>(_textDebug.width * Settings::aspectCorrection) + padding * 2,
_textDebug.height};
SDL_RenderFillRect(_renderer, &backgroundRect);
_textDebug.draw(_renderer, padding, y); _textDebug.draw(_renderer, padding, y);
}
y += _textDebug.height + lineSpacing; y += _textDebug.height + lineSpacing;
if (lineEnd == std::string::npos) if (lineEnd == std::string::npos)
@@ -108,4 +123,7 @@ void Interface::drawDebug()
lineStart = lineEnd + 1; lineStart = lineEnd + 1;
} }
SDL_SetRenderDrawColor(_renderer, previousR, previousG, previousB, previousA);
SDL_SetRenderDrawBlendMode(_renderer, previousBlendMode);
} }
+1
View File
@@ -170,6 +170,7 @@ void ConnectionReader::onUsbRead(libusb_transfer *transfer)
void ConnectionReader::readLoop() void ConnectionReader::readLoop()
{ {
setThreadName("usb-read"); setThreadName("usb-read");
setThreadPriority(ThreadPriority::Realtime);
timeval timeout{0, 100000}; timeval timeout{0, 100000};
log_d("USB reading thread started"); log_d("USB reading thread started");