diff --git a/app/streaming/audio/audio.cpp b/app/streaming/audio/audio.cpp index 0b0efef2..73bdff10 100644 --- a/app/streaming/audio/audio.cpp +++ b/app/streaming/audio/audio.cpp @@ -13,36 +13,87 @@ #include -IAudioRenderer* Session::createAudioRenderer() -{ -#if defined(HAVE_SOUNDIO) -#ifdef Q_OS_LINUX - // Default is SDL with libsoundio as an alternate - if (qgetenv("ML_AUDIO") == "libsoundio") { - return new SoundIoAudioRenderer(); - } - - return new SdlAudioRenderer(); -#else - // Default is libsoundio with SDL as an alternate - if (qgetenv("ML_AUDIO") == "SDL") { - return new SdlAudioRenderer(); - } - - return new SoundIoAudioRenderer(); -#endif -#elif defined(HAVE_SLAUDIO) - return new SLAudioRenderer(); -#else - return new SdlAudioRenderer(); -#endif +#define TRY_INIT_RENDERER(renderer, opusConfig) \ +{ \ + IAudioRenderer* __renderer = new renderer(); \ + if (__renderer->prepareForPlayback(opusConfig)) \ + return __renderer; \ + delete __renderer; \ } -int Session::getAudioRendererCapabilities() +IAudioRenderer* Session::createAudioRenderer(const POPUS_MULTISTREAM_CONFIGURATION opusConfig) { - IAudioRenderer* audioRenderer; + // Handle explicit ML_AUDIO setting and fail if the requested backend fails + QString mlAudio = qgetenv("ML_AUDIO").toLower(); + if (mlAudio == "sdl") { + TRY_INIT_RENDERER(SdlAudioRenderer, opusConfig) + return nullptr; + } +#ifdef HAVE_SOUNDIO + else if (mlAudio == "libsoundio") { + TRY_INIT_RENDERER(SoundIoAudioRenderer, opusConfig) + return nullptr; + } +#endif +#if defined(HAVE_SLAUDIO) + else if (mlAudio == "slaudio") { + TRY_INIT_RENDERER(SLAudioRenderer, opusConfig) + return nullptr; + } +#endif + else if (!mlAudio.isEmpty()) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "Unknown audio backend: %s", + SDL_getenv("ML_AUDIO")); + return nullptr; + } - audioRenderer = createAudioRenderer(); + // -------------- Automatic backend selection below this line --------------- + +#if defined(HAVE_SLAUDIO) + // Steam Link should always have SLAudio + TRY_INIT_RENDERER(SLAudioRenderer, opusConfig) +#endif + +#ifdef Q_OS_LINUX + // Linux defaults to SDL and fall backs to libsoundio + TRY_INIT_RENDERER(SdlAudioRenderer, opusConfig) +#ifdef HAVE_SOUNDIO + TRY_INIT_RENDERER(SoundIoAudioRenderer, opusConfig) +#endif +#else + // Windows and macOS default to libsoundio and fall back to SDL +#ifdef HAVE_SOUNDIO + TRY_INIT_RENDERER(SoundIoAudioRenderer, opusConfig) +#endif + TRY_INIT_RENDERER(SdlAudioRenderer, opusConfig) +#endif + + return nullptr; +} + +int Session::getAudioRendererCapabilities(int audioConfiguration) +{ + // Build a fake OPUS_MULTISTREAM_CONFIGURATION to give + // the renderer the channel count and sample rate. + OPUS_MULTISTREAM_CONFIGURATION opusConfig = {}; + opusConfig.sampleRate = 48000; + opusConfig.samplesPerFrame = 240; + + switch (audioConfiguration) + { + case AUDIO_CONFIGURATION_STEREO: + opusConfig.channelCount = 2; + break; + case AUDIO_CONFIGURATION_51_SURROUND: + opusConfig.channelCount = 6; + break; + default: + SDL_assert(false); + return 0; + } + + IAudioRenderer* audioRenderer = createAudioRenderer(&opusConfig); if (audioRenderer == nullptr) { return 0; } @@ -56,13 +107,6 @@ int Session::getAudioRendererCapabilities() bool Session::testAudio(int audioConfiguration) { - IAudioRenderer* audioRenderer; - - audioRenderer = createAudioRenderer(); - if (audioRenderer == nullptr) { - return false; - } - // Build a fake OPUS_MULTISTREAM_CONFIGURATION to give // the renderer the channel count and sample rate. OPUS_MULTISTREAM_CONFIGURATION opusConfig = {}; @@ -82,11 +126,14 @@ bool Session::testAudio(int audioConfiguration) return false; } - bool ret = audioRenderer->prepareForPlayback(&opusConfig); + IAudioRenderer* audioRenderer = createAudioRenderer(&opusConfig); + if (audioRenderer == nullptr) { + return false; + } delete audioRenderer; - return ret; + return true; } int Session::arInit(int /* audioConfiguration */, @@ -111,9 +158,8 @@ int Session::arInit(int /* audioConfiguration */, return -1; } - s_ActiveSession->m_AudioRenderer = s_ActiveSession->createAudioRenderer(); - if (!s_ActiveSession->m_AudioRenderer->prepareForPlayback(opusConfig)) { - delete s_ActiveSession->m_AudioRenderer; + s_ActiveSession->m_AudioRenderer = s_ActiveSession->createAudioRenderer(opusConfig); + if (s_ActiveSession->m_AudioRenderer == nullptr) { opus_multistream_decoder_destroy(s_ActiveSession->m_OpusDecoder); return -2; } @@ -211,11 +257,7 @@ void Session::arDecodeAndPlaySample(char* sampleData, int sampleLength) // so we return to real-time playback and don't accumulate latency. Uint32 audioReinitStartTime = SDL_GetTicks(); - s_ActiveSession->m_AudioRenderer = s_ActiveSession->createAudioRenderer(); - if (!s_ActiveSession->m_AudioRenderer->prepareForPlayback(&s_ActiveSession->m_AudioConfig)) { - delete s_ActiveSession->m_AudioRenderer; - s_ActiveSession->m_AudioRenderer = nullptr; - } + s_ActiveSession->m_AudioRenderer = s_ActiveSession->createAudioRenderer(&s_ActiveSession->m_AudioConfig); Uint32 audioReinitStopTime = SDL_GetTicks(); diff --git a/app/streaming/session.cpp b/app/streaming/session.cpp index e0bdb3d7..ee79f3d7 100644 --- a/app/streaming/session.cpp +++ b/app/streaming/session.cpp @@ -350,12 +350,6 @@ bool Session::initialize() "Encoder configured for %d slices per frame", slices); - LiInitializeAudioCallbacks(&m_AudioCallbacks); - m_AudioCallbacks.init = arInit; - m_AudioCallbacks.cleanup = arCleanup; - m_AudioCallbacks.decodeAndPlaySample = arDecodeAndPlaySample; - m_AudioCallbacks.capabilities = getAudioRendererCapabilities(); - LiInitializeStreamConfiguration(&m_StreamConfig); m_StreamConfig.width = m_Preferences->width; m_StreamConfig.height = m_Preferences->height; @@ -385,6 +379,12 @@ bool Session::initialize() break; } + LiInitializeAudioCallbacks(&m_AudioCallbacks); + m_AudioCallbacks.init = arInit; + m_AudioCallbacks.cleanup = arCleanup; + m_AudioCallbacks.decodeAndPlaySample = arDecodeAndPlaySample; + m_AudioCallbacks.capabilities = getAudioRendererCapabilities(m_StreamConfig.audioConfiguration); + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Audio configuration: %d", m_StreamConfig.audioConfiguration); diff --git a/app/streaming/session.h b/app/streaming/session.h index 4392d47c..1d27c914 100644 --- a/app/streaming/session.h +++ b/app/streaming/session.h @@ -66,13 +66,11 @@ private: StreamingPreferences::VideoDecoderSelection vds, int videoFormat, int width, int height, int frameRate); - IAudioRenderer* createAudioRenderer(); - - int detectAudioConfiguration(); + IAudioRenderer* createAudioRenderer(const POPUS_MULTISTREAM_CONFIGURATION opusConfig); bool testAudio(int audioConfiguration); - int getAudioRendererCapabilities(); + int getAudioRendererCapabilities(int audioConfiguration); void getWindowDimensions(int& x, int& y, int& width, int& height);