mirror of
https://github.com/niellun/FastCarPlay.git
synced 2026-06-07 09:38:25 +02:00
Thread priority, better debug overlay
This commit is contained in:
+65
-6
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
|
||||
#include "struct/video_buffer.h"
|
||||
#include "common/logger.h"
|
||||
@@ -393,7 +394,7 @@ void Application::loop()
|
||||
else
|
||||
{
|
||||
late = decoder.buffer.latestId() - latestFrameid > 1;
|
||||
if(!late || ++skipEvents > Settings::eventsSkip)
|
||||
if (!late || ++skipEvents > Settings::eventsSkip)
|
||||
{
|
||||
if (processFrameEvents(protocol.writeQueue, interface) && Settings::forceRedraw > 0)
|
||||
{
|
||||
@@ -405,18 +406,21 @@ void Application::loop()
|
||||
|
||||
if (_debug)
|
||||
{
|
||||
char debugBuffer[256];
|
||||
char debugBuffer[512];
|
||||
std::snprintf(debugBuffer, sizeof(debugBuffer),
|
||||
"FRAME: %u / %u [%d] droped %d\n"
|
||||
"TIME: %d delay %d\n"
|
||||
"%s\n"
|
||||
"FRAME: %u / %u [%d] dropped: %d render: %dms / %dms\n"
|
||||
"VIDEO: %u\n"
|
||||
"AUDIO-MAIN: %u\n"
|
||||
"AUDIO-AUX: %u\n"
|
||||
"OUT: %u",
|
||||
status().c_str(),
|
||||
latestFrameid,
|
||||
decoder.buffer.latestId(),
|
||||
decoder.buffer.latestId() - latestFrameid, dropframes,
|
||||
frameTime, delay,
|
||||
decoder.buffer.latestId() - latestFrameid,
|
||||
dropframes,
|
||||
frameTime,
|
||||
delay,
|
||||
protocol.videoStream.count(),
|
||||
protocol.audioStreamMain.count(),
|
||||
protocol.audioStreamAux.count(),
|
||||
@@ -444,3 +448,58 @@ void Application::loop()
|
||||
if (!Settings::isHeadless())
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ private:
|
||||
int processKey(SDL_Keysym key);
|
||||
bool processSystemEvent(const SDL_Event &e);
|
||||
bool processFrameEvents(AtomicQueue<Message> &queue, Renderer &renderer);
|
||||
const std::string status() const;
|
||||
|
||||
void loop();
|
||||
|
||||
|
||||
+100
-9
@@ -1,23 +1,114 @@
|
||||
#ifndef SRC_HELPER_THREADING
|
||||
#define SRC_HELPER_THREADING
|
||||
|
||||
#include <thread>
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
#include <pthread.h>
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include <libavutil/error.h>
|
||||
}
|
||||
#if defined(__linux__)
|
||||
#include <sched.h>
|
||||
#elif defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
inline void setThreadName(const char *name)
|
||||
inline void setThreadName(const char* name)
|
||||
{
|
||||
#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__)
|
||||
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
|
||||
(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, ¶m) == 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
|
||||
}
|
||||
|
||||
|
||||
+20
-2
@@ -24,7 +24,7 @@ Interface::~Interface()
|
||||
|
||||
bool Interface::render(AVFrame *frame)
|
||||
{
|
||||
if(!frame)
|
||||
if (!frame)
|
||||
return false;
|
||||
|
||||
if (_render == nullptr || frame->width != _textureWidth || frame->height != _textureHeight)
|
||||
@@ -91,7 +91,14 @@ void Interface::drawDebug()
|
||||
|
||||
constexpr int padding = 8;
|
||||
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;
|
||||
int y = padding;
|
||||
|
||||
@@ -100,7 +107,15 @@ void Interface::drawDebug()
|
||||
size_t lineEnd = _debugText.find('\n', lineStart);
|
||||
std::string line = _debugText.substr(lineStart, lineEnd - lineStart);
|
||||
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);
|
||||
}
|
||||
y += _textDebug.height + lineSpacing;
|
||||
|
||||
if (lineEnd == std::string::npos)
|
||||
@@ -108,4 +123,7 @@ void Interface::drawDebug()
|
||||
|
||||
lineStart = lineEnd + 1;
|
||||
}
|
||||
|
||||
SDL_SetRenderDrawColor(_renderer, previousR, previousG, previousB, previousA);
|
||||
SDL_SetRenderDrawBlendMode(_renderer, previousBlendMode);
|
||||
}
|
||||
|
||||
@@ -170,6 +170,7 @@ void ConnectionReader::onUsbRead(libusb_transfer *transfer)
|
||||
void ConnectionReader::readLoop()
|
||||
{
|
||||
setThreadName("usb-read");
|
||||
setThreadPriority(ThreadPriority::Realtime);
|
||||
timeval timeout{0, 100000};
|
||||
|
||||
log_d("USB reading thread started");
|
||||
|
||||
Reference in New Issue
Block a user