Fixes to SDL audio renderer and autodetection support

This commit is contained in:
Cameron Gutman
2018-09-13 07:46:01 -07:00
parent 12496e4432
commit 64bc189010
7 changed files with 59 additions and 88 deletions
+19 -7
View File
@@ -70,8 +70,7 @@ int Session::arInit(int /* audioConfiguration */,
return -2;
}
s_ActiveSession->m_AudioRenderer->prepareForPlayback(opusConfig);
if (s_ActiveSession->m_AudioRenderer == nullptr) {
if (!s_ActiveSession->m_AudioRenderer->prepareForPlayback(opusConfig)) {
delete s_ActiveSession->m_AudioRenderer;
opus_multistream_decoder_destroy(s_ActiveSession->m_OpusDecoder);
return -3;
@@ -86,12 +85,21 @@ int Session::arInit(int /* audioConfiguration */,
void Session::arCleanup()
{
delete s_ActiveSession->m_AudioRenderer;
// m_AudioRenderer is deleted in cleanupAudioRenderer()
opus_multistream_decoder_destroy(s_ActiveSession->m_OpusDecoder);
s_ActiveSession->m_OpusDecoder = nullptr;
}
// This is called on the main thread
void Session::cleanupAudioRendererOnMainThread()
{
SDL_AtomicLock(&m_AudioRendererLock);
delete m_AudioRenderer;
m_AudioRenderer = nullptr;
SDL_AtomicUnlock(&m_AudioRendererLock);
}
void Session::arDecodeAndPlaySample(char* sampleData, int sampleLength)
{
int samplesDecoded;
@@ -103,9 +111,13 @@ void Session::arDecodeAndPlaySample(char* sampleData, int sampleLength)
SAMPLES_PER_FRAME,
0);
if (samplesDecoded > 0) {
s_ActiveSession->m_AudioRenderer->submitAudio(s_ActiveSession->m_OpusDecodeBuffer,
static_cast<int>(sizeof(short) *
samplesDecoded *
s_ActiveSession->m_AudioConfig.channelCount));
SDL_AtomicLock(&s_ActiveSession->m_AudioRendererLock);
if (s_ActiveSession->m_AudioRenderer != nullptr) {
s_ActiveSession->m_AudioRenderer->submitAudio(s_ActiveSession->m_OpusDecodeBuffer,
static_cast<int>(sizeof(short) *
samplesDecoded *
s_ActiveSession->m_AudioConfig.channelCount));
}
SDL_AtomicUnlock(&s_ActiveSession->m_AudioRendererLock);
}
}
+28 -72
View File
@@ -3,6 +3,7 @@
#include <Limelight.h>
#include <SDL.h>
#include <QAudioDeviceInfo>
#include <QtGlobal>
#define MIN_QUEUED_FRAMES 2
@@ -10,69 +11,31 @@
#define STOP_THE_WORLD_LIMIT 20
#define DROP_RATIO_DENOM 32
// Detecting this with SDL is quite problematic, so we'll use Qt's
// multimedia framework to do so. It appears to be actually
// accurate on Linux and macOS, unlike using SDL and relying
// on a channel change in the format received.
int SdlAudioRenderer::detectAudioConfiguration()
{
SDL_AudioSpec want, have;
SDL_AudioDeviceID dev;
int ret;
if (SDL_InitSubSystem(SDL_INIT_AUDIO) != 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_InitSubSystem(SDL_INIT_AUDIO) failed: %s",
SDL_GetError());
return AUDIO_CONFIGURATION_STEREO;
}
SDL_zero(want);
want.freq = 48000;
want.format = AUDIO_S16;
want.channels = 6;
want.samples = 1024;
// Try to open for 5.1 surround sound, but allow SDL to tell us that's
// not available.
dev = SDL_OpenAudioDevice(NULL, 0, &want, &have, SDL_AUDIO_ALLOW_CHANNELS_CHANGE);
if (dev == 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Failed to open audio device");
// We'll probably have issues during audio stream init, but we'll
// try anyway
ret = AUDIO_CONFIGURATION_STEREO;
goto Exit;
}
SDL_CloseAudioDevice(dev);
int preferredChannelCount = QAudioDeviceInfo::defaultOutputDevice().preferredFormat().channelCount();
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Audio device has %d channels", have.channels);
"Audio output device prefers %d channel configuration",
preferredChannelCount);
if (have.channels > 2) {
// We don't support quadraphonic or 7.1 surround, but SDL
// should be able to downmix or upmix better from 5.1 than
// from stereo, so use 5.1 in non-stereo cases.
ret = AUDIO_CONFIGURATION_51_SURROUND;
// We can better downmix 5.1 to quad than we can upmix stereo
if (preferredChannelCount > 2) {
return AUDIO_CONFIGURATION_51_SURROUND;
}
else {
ret = AUDIO_CONFIGURATION_STEREO;
return AUDIO_CONFIGURATION_STEREO;
}
Exit:
SDL_QuitSubSystem(SDL_INIT_AUDIO);
return ret;
}
bool SdlAudioRenderer::testAudio(int audioConfiguration)
{
SDL_AudioSpec want, have;
SDL_AudioDeviceID dev;
bool ret;
if (SDL_InitSubSystem(SDL_INIT_AUDIO) != 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Audio test - SDL_InitSubSystem(SDL_INIT_AUDIO) failed: %s",
SDL_GetError());
return false;
}
SDL_zero(want);
want.freq = 48000;
@@ -88,8 +51,7 @@ bool SdlAudioRenderer::testAudio(int audioConfiguration)
break;
default:
SDL_assert(false);
ret = false;
goto Exit;
return false;
}
// Test audio device for functionality
@@ -98,8 +60,7 @@ bool SdlAudioRenderer::testAudio(int audioConfiguration)
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Audio test - Failed to open audio device: %s",
SDL_GetError());
ret = false;
goto Exit;
return false;
}
SDL_CloseAudioDevice(dev);
@@ -107,12 +68,7 @@ bool SdlAudioRenderer::testAudio(int audioConfiguration)
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Audio test - Successful with %d channels",
want.channels);
ret = true;
Exit:
SDL_QuitSubSystem(SDL_INIT_AUDIO);
return ret;
return true;
}
SdlAudioRenderer::SdlAudioRenderer()
@@ -123,20 +79,18 @@ SdlAudioRenderer::SdlAudioRenderer()
m_SampleIndex(0),
m_BaselinePendingData(0)
{
}
bool SdlAudioRenderer::prepareForPlayback(const OPUS_MULTISTREAM_CONFIGURATION* opusConfig)
{
SDL_AudioSpec want, have;
SDL_assert(!SDL_WasInit(SDL_INIT_AUDIO));
if (SDL_InitSubSystem(SDL_INIT_AUDIO) != 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_InitSubSystem(SDL_INIT_AUDIO) failed: %s",
SDL_GetError());
return -1;
SDL_assert(SDL_WasInit(SDL_INIT_AUDIO));
}
}
bool SdlAudioRenderer::prepareForPlayback(const OPUS_MULTISTREAM_CONFIGURATION* opusConfig)
{
SDL_AudioSpec want, have;
SDL_zero(want);
want.freq = opusConfig->sampleRate;
@@ -155,7 +109,7 @@ bool SdlAudioRenderer::prepareForPlayback(const OPUS_MULTISTREAM_CONFIGURATION*
"Failed to open audio device: %s",
SDL_GetError());
SDL_QuitSubSystem(SDL_INIT_AUDIO);
return -1;
return false;
}
// SDL counts pending samples in the queued
@@ -182,14 +136,16 @@ bool SdlAudioRenderer::prepareForPlayback(const OPUS_MULTISTREAM_CONFIGURATION*
// Start playback
SDL_PauseAudioDevice(m_AudioDevice, 0);
return 0;
return true;
}
SdlAudioRenderer::~SdlAudioRenderer()
{
// Stop playback
SDL_PauseAudioDevice(m_AudioDevice, 1);
SDL_CloseAudioDevice(m_AudioDevice);
if (m_AudioDevice != 0) {
// Stop playback
SDL_PauseAudioDevice(m_AudioDevice, 1);
SDL_CloseAudioDevice(m_AudioDevice);
}
SDL_QuitSubSystem(SDL_INIT_AUDIO);
SDL_assert(!SDL_WasInit(SDL_INIT_AUDIO));
+5 -1
View File
@@ -279,7 +279,8 @@ Session::Session(NvComputer* computer, NvApp& app)
m_DisplayOriginY(0),
m_PendingWindowedTransition(false),
m_OpusDecoder(nullptr),
m_AudioRenderer(nullptr)
m_AudioRenderer(nullptr),
m_AudioRendererLock(0)
{
}
@@ -1110,6 +1111,9 @@ DispatchDeferredCleanup:
m_VideoDecoder = nullptr;
SDL_AtomicUnlock(&m_DecoderLock);
// Destroy the audio renderer which must also be done on the main thread
cleanupAudioRendererOnMainThread();
SDL_DestroyWindow(m_Window);
if (iconSurface != nullptr) {
SDL_FreeSurface(iconSurface);
+3
View File
@@ -54,6 +54,8 @@ private:
int detectAudioConfiguration();
void cleanupAudioRendererOnMainThread();
bool testAudio(int audioConfiguration);
void getWindowDimensions(int& x, int& y,
@@ -124,6 +126,7 @@ private:
short m_OpusDecodeBuffer[MAX_CHANNELS * SAMPLES_PER_FRAME];
IAudioRenderer* m_AudioRenderer;
OPUS_MULTISTREAM_CONFIGURATION m_AudioConfig;
SDL_SpinLock m_AudioRendererLock;
static AUDIO_RENDERER_CALLBACKS k_AudioCallbacks;
static CONNECTION_LISTENER_CALLBACKS k_ConnCallbacks;