From 605d52f16052f8d0d52e374d73de46f8543cb056 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 22 Sep 2018 20:03:41 -0700 Subject: [PATCH] Don't block in audio/video renderer callbacks while the renderer is being destroyed --- app/streaming/audio/audio.cpp | 17 +++++++++------- app/streaming/session.cpp | 38 +++++++++++++++++++++-------------- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/app/streaming/audio/audio.cpp b/app/streaming/audio/audio.cpp index df9d0e15..49dce3d1 100644 --- a/app/streaming/audio/audio.cpp +++ b/app/streaming/audio/audio.cpp @@ -120,13 +120,16 @@ void Session::arDecodeAndPlaySample(char* sampleData, int sampleLength) SAMPLES_PER_FRAME, 0); if (samplesDecoded > 0) { - SDL_AtomicLock(&s_ActiveSession->m_AudioRendererLock); - if (s_ActiveSession->m_AudioRenderer != nullptr) { - s_ActiveSession->m_AudioRenderer->submitAudio(s_ActiveSession->m_OpusDecodeBuffer, - static_cast(sizeof(short) * - samplesDecoded * - s_ActiveSession->m_AudioConfig.channelCount)); + // If we can't acquire the lock, that means we're being destroyed + // so don't even bother trying to wait. + if (SDL_AtomicTryLock(&s_ActiveSession->m_AudioRendererLock)) { + if (s_ActiveSession->m_AudioRenderer != nullptr) { + s_ActiveSession->m_AudioRenderer->submitAudio(s_ActiveSession->m_OpusDecodeBuffer, + static_cast(sizeof(short) * + samplesDecoded * + s_ActiveSession->m_AudioConfig.channelCount)); + } + SDL_AtomicUnlock(&s_ActiveSession->m_AudioRendererLock); } - SDL_AtomicUnlock(&s_ActiveSession->m_AudioRendererLock); } } diff --git a/app/streaming/session.cpp b/app/streaming/session.cpp index a6369f0f..94b2c2d7 100644 --- a/app/streaming/session.cpp +++ b/app/streaming/session.cpp @@ -170,25 +170,33 @@ int Session::drSubmitDecodeUnit(PDECODE_UNIT du) // Use a lock since we'll be yanking this decoder out // from underneath the session when we initiate destruction. // We need to destroy the decoder on the main thread to satisfy - // some API constraints (like DXVA2). + // some API constraints (like DXVA2). If we can't acquire it, + // that means the decoder is about to be destroyed, so we can + // safely return DR_OK and wait for m_NeedsIdr to be set by + // the decoder reinitialization code. - SDL_AtomicLock(&s_ActiveSession->m_DecoderLock); + if (SDL_AtomicTryLock(&s_ActiveSession->m_DecoderLock)) { + if (s_ActiveSession->m_NeedsIdr) { + // If we reset our decoder, we'll need to request an IDR frame + s_ActiveSession->m_NeedsIdr = false; + SDL_AtomicUnlock(&s_ActiveSession->m_DecoderLock); + return DR_NEED_IDR; + } - if (s_ActiveSession->m_NeedsIdr) { - // If we reset our decoder, we'll need to request an IDR frame - s_ActiveSession->m_NeedsIdr = false; - SDL_AtomicUnlock(&s_ActiveSession->m_DecoderLock); - return DR_NEED_IDR; - } - - IVideoDecoder* decoder = s_ActiveSession->m_VideoDecoder; - if (decoder != nullptr) { - int ret = decoder->submitDecodeUnit(du); - SDL_AtomicUnlock(&s_ActiveSession->m_DecoderLock); - return ret; + IVideoDecoder* decoder = s_ActiveSession->m_VideoDecoder; + if (decoder != nullptr) { + int ret = decoder->submitDecodeUnit(du); + SDL_AtomicUnlock(&s_ActiveSession->m_DecoderLock); + return ret; + } + else { + SDL_AtomicUnlock(&s_ActiveSession->m_DecoderLock); + return DR_OK; + } } else { - SDL_AtomicUnlock(&s_ActiveSession->m_DecoderLock); + // Decoder is going away. Ignore anything coming in until + // the lock is released. return DR_OK; } }