mirror of
https://github.com/niellun/FastCarPlay.git
synced 2026-09-23 02:10:42 +02:00
Thread priority, better debug overlay
This commit is contained in:
+65
-6
@@ -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();
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
@@ -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, ¶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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+20
-2
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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");
|
||||||
|
|||||||
Reference in New Issue
Block a user