Switch the decoder lock to a mutex

It can be held for non-trivial amounts of time.
This commit is contained in:
Cameron Gutman
2025-10-12 15:47:09 -05:00
parent c9cb64f90b
commit c0d38ee78f
2 changed files with 23 additions and 18 deletions

View File

@@ -213,12 +213,12 @@ void Session::clSetHdrMode(bool enabled)
// If we're in the process of recreating our decoder when we get // If we're in the process of recreating our decoder when we get
// this callback, we'll drop it. The main thread will make the // this callback, we'll drop it. The main thread will make the
// callback when it finishes creating the new decoder. // callback when it finishes creating the new decoder.
if (SDL_AtomicTryLock(&s_ActiveSession->m_DecoderLock)) { if (SDL_TryLockMutex(s_ActiveSession->m_DecoderLock) == 0) {
IVideoDecoder* decoder = s_ActiveSession->m_VideoDecoder; IVideoDecoder* decoder = s_ActiveSession->m_VideoDecoder;
if (decoder != nullptr) { if (decoder != nullptr) {
decoder->setHdrMode(enabled); decoder->setHdrMode(enabled);
} }
SDL_AtomicUnlock(&s_ActiveSession->m_DecoderLock); SDL_UnlockMutex(s_ActiveSession->m_DecoderLock);
} }
} }
@@ -375,15 +375,15 @@ int Session::drSubmitDecodeUnit(PDECODE_UNIT du)
// safely return DR_OK and wait for the IDR frame request by // safely return DR_OK and wait for the IDR frame request by
// the decoder reinitialization code. // the decoder reinitialization code.
if (SDL_AtomicTryLock(&s_ActiveSession->m_DecoderLock)) { if (SDL_TryLockMutex(s_ActiveSession->m_DecoderLock) == 0) {
IVideoDecoder* decoder = s_ActiveSession->m_VideoDecoder; IVideoDecoder* decoder = s_ActiveSession->m_VideoDecoder;
if (decoder != nullptr) { if (decoder != nullptr) {
int ret = decoder->submitDecodeUnit(du); int ret = decoder->submitDecodeUnit(du);
SDL_AtomicUnlock(&s_ActiveSession->m_DecoderLock); SDL_UnlockMutex(s_ActiveSession->m_DecoderLock);
return ret; return ret;
} }
else { else {
SDL_AtomicUnlock(&s_ActiveSession->m_DecoderLock); SDL_UnlockMutex(s_ActiveSession->m_DecoderLock);
return DR_OK; return DR_OK;
} }
} }
@@ -570,7 +570,7 @@ Session::Session(NvComputer* computer, NvApp& app, StreamingPreferences *prefere
m_App(app), m_App(app),
m_Window(nullptr), m_Window(nullptr),
m_VideoDecoder(nullptr), m_VideoDecoder(nullptr),
m_DecoderLock(0), m_DecoderLock(SDL_CreateMutex()),
m_AudioMuted(false), m_AudioMuted(false),
m_QtWindow(nullptr), m_QtWindow(nullptr),
m_UnexpectedTermination(true), // Failure prior to streaming is unexpected m_UnexpectedTermination(true), // Failure prior to streaming is unexpected
@@ -587,6 +587,14 @@ Session::Session(NvComputer* computer, NvApp& app, StreamingPreferences *prefere
{ {
} }
Session::~Session()
{
// NB: This may not get destroyed for a long time! Don't put any non-trivial cleanup here.
// Use Session::exec() or DeferredSessionCleanupTask instead.
SDL_DestroyMutex(m_DecoderLock);
}
bool Session::initialize() bool Session::initialize()
{ {
#ifdef Q_OS_DARWIN #ifdef Q_OS_DARWIN
@@ -1482,10 +1490,10 @@ void Session::toggleFullscreen()
// On Apple Silicon Macs, the AVSampleBufferDisplayLayer may cause WindowServer // On Apple Silicon Macs, the AVSampleBufferDisplayLayer may cause WindowServer
// to deadlock when transitioning out of fullscreen. Destroy the decoder before // to deadlock when transitioning out of fullscreen. Destroy the decoder before
// exiting fullscreen as a workaround. See issue #973. // exiting fullscreen as a workaround. See issue #973.
SDL_AtomicLock(&m_DecoderLock); SDL_LockMutex(m_DecoderLock);
delete m_VideoDecoder; delete m_VideoDecoder;
m_VideoDecoder = nullptr; m_VideoDecoder = nullptr;
SDL_AtomicUnlock(&m_DecoderLock); SDL_UnlockMutex(m_DecoderLock);
#endif #endif
// Actually enter/leave fullscreen // Actually enter/leave fullscreen
@@ -2216,7 +2224,7 @@ void Session::execInternal()
event.type); event.type);
} }
SDL_AtomicLock(&m_DecoderLock); SDL_LockMutex(m_DecoderLock);
// Destroy the old decoder // Destroy the old decoder
delete m_VideoDecoder; delete m_VideoDecoder;
@@ -2262,7 +2270,7 @@ void Session::execInternal()
enableVsync && m_Preferences->framePacing, enableVsync && m_Preferences->framePacing,
false, false,
s_ActiveSession->m_VideoDecoder)) { s_ActiveSession->m_VideoDecoder)) {
SDL_AtomicUnlock(&m_DecoderLock); SDL_UnlockMutex(m_DecoderLock);
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Failed to recreate decoder after reset"); "Failed to recreate decoder after reset");
emit displayLaunchError(tr("Unable to initialize video decoder. Please check your streaming settings and try again.")); emit displayLaunchError(tr("Unable to initialize video decoder. Please check your streaming settings and try again."));
@@ -2288,7 +2296,7 @@ void Session::execInternal()
// After a window resize, we need to reset the pointer lock region // After a window resize, we need to reset the pointer lock region
m_InputHandler->updatePointerRegionLock(); m_InputHandler->updatePointerRegionLock();
SDL_AtomicUnlock(&m_DecoderLock); SDL_UnlockMutex(m_DecoderLock);
break; break;
case SDL_KEYUP: case SDL_KEYUP:
@@ -2367,10 +2375,10 @@ DispatchDeferredCleanup:
// Destroy the decoder, since this must be done on the main thread // Destroy the decoder, since this must be done on the main thread
// NB: This must happen before LiStopConnection() for pull-based // NB: This must happen before LiStopConnection() for pull-based
// decoders. // decoders.
SDL_AtomicLock(&m_DecoderLock); SDL_LockMutex(m_DecoderLock);
delete m_VideoDecoder; delete m_VideoDecoder;
m_VideoDecoder = nullptr; m_VideoDecoder = nullptr;
SDL_AtomicUnlock(&m_DecoderLock); SDL_UnlockMutex(m_DecoderLock);
// Propagate state changes from the SDL window back to the Qt window // Propagate state changes from the SDL window back to the Qt window
// //

View File

@@ -100,10 +100,7 @@ class Session : public QObject
public: public:
explicit Session(NvComputer* computer, NvApp& app, StreamingPreferences *preferences = nullptr); explicit Session(NvComputer* computer, NvApp& app, StreamingPreferences *preferences = nullptr);
virtual ~Session();
// NB: This may not get destroyed for a long time! Don't put any cleanup here.
// Use Session::exec() or DeferredSessionCleanupTask instead.
virtual ~Session() {};
Q_INVOKABLE void exec(QWindow* qtWindow); Q_INVOKABLE void exec(QWindow* qtWindow);
@@ -255,7 +252,7 @@ private:
NvApp m_App; NvApp m_App;
SDL_Window* m_Window; SDL_Window* m_Window;
IVideoDecoder* m_VideoDecoder; IVideoDecoder* m_VideoDecoder;
SDL_SpinLock m_DecoderLock; SDL_mutex* m_DecoderLock;
bool m_AudioDisabled; bool m_AudioDisabled;
bool m_AudioMuted; bool m_AudioMuted;
Uint32 m_FullScreenFlag; Uint32 m_FullScreenFlag;