diff --git a/app/app.pro b/app/app.pro index c0044c58..8dd244e9 100644 --- a/app/app.pro +++ b/app/app.pro @@ -126,7 +126,8 @@ SOURCES += \ path.cpp \ settings/mappingmanager.cpp \ gui/sdlgamepadkeynavigation.cpp \ - streaming/video/overlaymanager.cpp + streaming/video/overlaymanager.cpp \ + streaming/sdlhelper.cpp HEADERS += \ utils.h \ @@ -153,7 +154,8 @@ HEADERS += \ path.h \ settings/mappingmanager.h \ gui/sdlgamepadkeynavigation.h \ - streaming/video/overlaymanager.h + streaming/video/overlaymanager.h \ + streaming/sdlhelper.h # Platform-specific renderers and decoders ffmpeg { diff --git a/app/streaming/sdlhelper.cpp b/app/streaming/sdlhelper.cpp new file mode 100644 index 00000000..dbca3780 --- /dev/null +++ b/app/streaming/sdlhelper.cpp @@ -0,0 +1,45 @@ +#include "sdlhelper.h" + +SDL_cond* SDLHelper::s_EventCond; +SDL_mutex* SDLHelper::s_EventMutex; + +void SDLHelper::initializeIfNeeded() +{ + if (!s_EventCond) { + s_EventCond = SDL_CreateCond(); + } + if (!s_EventMutex) { + s_EventMutex = SDL_CreateMutex(); + } +} + +void SDLHelper::waitEvent(SDL_Event* event) +{ + initializeIfNeeded(); + + // We explicitly use SDL_PollEvent() and SDL_Delay() because + // SDL_WaitEventTimeout() has an internal SDL_Delay(10) inside which + // blocks this thread too long for high polling rate mice and high + // refresh rate displays. + while (!SDL_PollEvent(event)) { + // Sleep for up to 1 ms or until we are woken up by + // SDLHelper::pushEvent(). + // FIXME: SDL should do this internally + SDL_LockMutex(s_EventMutex); + SDL_CondWaitTimeout(s_EventCond, s_EventMutex, 1); + SDL_UnlockMutex(s_EventMutex); + continue; + } +} + +void SDLHelper::pushEvent(SDL_Event* event) +{ + initializeIfNeeded(); + + SDL_PushEvent(event); + + // Immediately wake up the other waiting thread + SDL_LockMutex(s_EventMutex); + SDL_CondSignal(s_EventCond); + SDL_UnlockMutex(s_EventMutex); +} diff --git a/app/streaming/sdlhelper.h b/app/streaming/sdlhelper.h new file mode 100644 index 00000000..a6179a06 --- /dev/null +++ b/app/streaming/sdlhelper.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +class SDLHelper +{ +public: + static void waitEvent(SDL_Event* event); + static void pushEvent(SDL_Event* event); + +private: + static void initializeIfNeeded(); + + static SDL_cond* s_EventCond; + static SDL_mutex* s_EventMutex; +}; diff --git a/app/streaming/session.cpp b/app/streaming/session.cpp index 1d8a4f91..1cdd50be 100644 --- a/app/streaming/session.cpp +++ b/app/streaming/session.cpp @@ -1,6 +1,7 @@ #include "session.h" #include "settings/streamingpreferences.h" #include "streaming/streamutils.h" +#include "streaming/sdlhelper.h" #include #include @@ -981,14 +982,8 @@ void Session::exec(int displayOriginX, int displayOriginY) // because we want to suspend all Qt processing until the stream is over. SDL_Event event; for (;;) { - // We explicitly use SDL_PollEvent() and SDL_Delay() because - // SDL_WaitEvent() has an internal SDL_Delay(10) inside which - // blocks this thread too long for high polling rate mice and high - // refresh rate displays. - if (!SDL_PollEvent(&event)) { - SDL_Delay(1); - continue; - } + SDLHelper::waitEvent(&event); + switch (event.type) { case SDL_QUIT: SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, diff --git a/app/streaming/video/decoder.h b/app/streaming/video/decoder.h index ae826f80..40574c15 100644 --- a/app/streaming/video/decoder.h +++ b/app/streaming/video/decoder.h @@ -3,6 +3,7 @@ #include #include #include "settings/streamingpreferences.h" +#include "streaming/sdlhelper.h" #define SDL_CODE_FRAME_READY 0 @@ -53,6 +54,6 @@ public: event.user.data1 = data1; event.user.data2 = data2; - SDL_PushEvent(&event); + SDLHelper::pushEvent(&event); } };