Cap queued audio at 40 ms on Steam Link

This commit is contained in:
Cameron Gutman 2019-05-11 19:09:59 -07:00
parent c2b12868bb
commit b3ee7a635f
7 changed files with 58 additions and 15 deletions

View File

@ -156,16 +156,22 @@ void Session::arDecodeAndPlaySample(char* sampleData, int sampleLength)
(short*)buffer, (short*)buffer,
desiredSize / sizeof(short) / s_ActiveSession->m_AudioConfig.channelCount, desiredSize / sizeof(short) / s_ActiveSession->m_AudioConfig.channelCount,
0); 0);
// Update desiredSize with the number of bytes actually populated by the decoding operation
if (samplesDecoded > 0) { if (samplesDecoded > 0) {
SDL_assert(desiredSize >= sizeof(short) * samplesDecoded * s_ActiveSession->m_AudioConfig.channelCount); SDL_assert(desiredSize >= sizeof(short) * samplesDecoded * s_ActiveSession->m_AudioConfig.channelCount);
desiredSize = sizeof(short) * samplesDecoded * s_ActiveSession->m_AudioConfig.channelCount; desiredSize = sizeof(short) * samplesDecoded * s_ActiveSession->m_AudioConfig.channelCount;
if (!s_ActiveSession->m_AudioRenderer->submitAudio(desiredSize)) { }
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, else {
"Reinitializing audio renderer after failure"); desiredSize = 0;
}
delete s_ActiveSession->m_AudioRenderer; if (!s_ActiveSession->m_AudioRenderer->submitAudio(desiredSize)) {
s_ActiveSession->m_AudioRenderer = nullptr; SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION,
} "Reinitializing audio renderer after failure");
delete s_ActiveSession->m_AudioRenderer;
s_ActiveSession->m_AudioRenderer = nullptr;
} }
} }

View File

@ -2,9 +2,6 @@
#include <Limelight.h> #include <Limelight.h>
#define MAX_CHANNELS 6
#define SAMPLES_PER_FRAME 240
class IAudioRenderer class IAudioRenderer
{ {
public: public:

View File

@ -87,6 +87,11 @@ void* SdlAudioRenderer::getAudioBuffer(int*)
bool SdlAudioRenderer::submitAudio(int bytesWritten) bool SdlAudioRenderer::submitAudio(int bytesWritten)
{ {
if (bytesWritten == 0) {
// Nothing to do
return true;
}
if (SDL_QueueAudio(m_AudioDevice, m_AudioBuffer, bytesWritten) < 0) { if (SDL_QueueAudio(m_AudioDevice, m_AudioBuffer, bytesWritten) < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"Failed to queue audio sample: %s", "Failed to queue audio sample: %s",

View File

@ -4,7 +4,8 @@
SLAudioRenderer::SLAudioRenderer() SLAudioRenderer::SLAudioRenderer()
: m_AudioContext(nullptr), : m_AudioContext(nullptr),
m_AudioStream(nullptr) m_AudioStream(nullptr),
m_AudioBuffer(nullptr)
{ {
SLAudio_SetLogFunction(SLAudioRenderer::slLogCallback, nullptr); SLAudio_SetLogFunction(SLAudioRenderer::slLogCallback, nullptr);
} }
@ -18,6 +19,7 @@ bool SLAudioRenderer::prepareForPlayback(const OPUS_MULTISTREAM_CONFIGURATION* o
return false; return false;
} }
m_FrameDuration = opusConfig->samplesPerFrame / 48;
m_AudioBufferSize = opusConfig->samplesPerFrame * sizeof(short) * opusConfig->channelCount; m_AudioBufferSize = opusConfig->samplesPerFrame * sizeof(short) * opusConfig->channelCount;
m_AudioStream = SLAudio_CreateStream(m_AudioContext, m_AudioStream = SLAudio_CreateStream(m_AudioContext,
opusConfig->sampleRate, opusConfig->sampleRate,
@ -31,7 +33,8 @@ bool SLAudioRenderer::prepareForPlayback(const OPUS_MULTISTREAM_CONFIGURATION* o
} }
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Using SLAudio renderer"); "Using SLAudio renderer with %d ms frames",
m_FrameDuration);
return true; return true;
} }
@ -39,11 +42,21 @@ bool SLAudioRenderer::prepareForPlayback(const OPUS_MULTISTREAM_CONFIGURATION* o
void* SLAudioRenderer::getAudioBuffer(int* size) void* SLAudioRenderer::getAudioBuffer(int* size)
{ {
SDL_assert(*size == m_AudioBufferSize); SDL_assert(*size == m_AudioBufferSize);
return SLAudio_BeginFrame(m_AudioStream);
if (m_AudioBuffer == nullptr) {
m_AudioBuffer = SLAudio_BeginFrame(m_AudioStream);
}
return m_AudioBuffer;
} }
SLAudioRenderer::~SLAudioRenderer() SLAudioRenderer::~SLAudioRenderer()
{ {
if (m_AudioBuffer != nullptr) {
memset(m_AudioBuffer, 0, m_AudioBufferSize);
SLAudio_SubmitFrame(m_AudioStream);
}
if (m_AudioStream != nullptr) { if (m_AudioStream != nullptr) {
SLAudio_FreeStream(m_AudioStream); SLAudio_FreeStream(m_AudioStream);
} }
@ -53,9 +66,24 @@ SLAudioRenderer::~SLAudioRenderer()
} }
} }
bool SLAudioRenderer::submitAudio(int) bool SLAudioRenderer::submitAudio(int bytesWritten)
{ {
SLAudio_SubmitFrame(m_AudioStream); if (bytesWritten == 0) {
// This buffer will be reused next time
return true;
}
// Only allow up to 40 ms of queued audio
if (LiGetPendingAudioFrames() * m_FrameDuration < 40) {
SLAudio_SubmitFrame(m_AudioStream);
m_AudioBuffer = nullptr;
}
else {
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION,
"Too many queued audio frames: %d",
LiGetPendingAudioFrames());
}
return true; return true;
} }

View File

@ -22,5 +22,7 @@ private:
CSLAudioContext* m_AudioContext; CSLAudioContext* m_AudioContext;
CSLAudioStream* m_AudioStream; CSLAudioStream* m_AudioStream;
void* m_AudioBuffer;
int m_AudioBufferSize; int m_AudioBufferSize;
int m_FrameDuration;
}; };

View File

@ -303,6 +303,11 @@ bool SoundIoAudioRenderer::submitAudio(int bytesWritten)
return false; return false;
} }
if (bytesWritten == 0) {
// Nothing to do
return true;
}
// Flush events to update with new device arrivals // Flush events to update with new device arrivals
soundio_flush_events(m_SoundIo); soundio_flush_events(m_SoundIo);

@ -1 +1 @@
Subproject commit 59481c085a7f774c5d30374636f8bc75da7c676c Subproject commit dffe51e885bcb5e09f90288f30268846f08c25de