diff options
author | Chris Robinson <[email protected]> | 2019-01-03 18:16:46 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2019-01-03 18:16:46 -0800 |
commit | 0a6748156d61b3bfe71766f208002dda791a3924 (patch) | |
tree | c7619c8b8d5ba273417e85400fc237e5e10e735a | |
parent | 21a17620e37dce28295cbc43b692d7fe910efd67 (diff) |
Make sure the OpenSL capture buffer queue has the correct size
The ring buffer size may round up and have more queueable elements than OpenSL
was allocated with, leading to errors when queueing those extra elements. Now
OpenSL allocates the same number of elements that can be written to the ring
buffer.
-rw-r--r-- | Alc/backends/opensl.cpp | 139 |
1 files changed, 71 insertions, 68 deletions
diff --git a/Alc/backends/opensl.cpp b/Alc/backends/opensl.cpp index 69f9cda4..ce67bd64 100644 --- a/Alc/backends/opensl.cpp +++ b/Alc/backends/opensl.cpp @@ -26,6 +26,7 @@ #include <stdlib.h> #include <jni.h> +#include <new> #include <thread> #include <functional> @@ -304,7 +305,7 @@ ALCenum OpenSLPlayback::open(const ALCchar *name) return ALC_INVALID_VALUE; // create engine - SLresult result{slCreateEngine(&mEngineObj, 0, NULL, 0, NULL, NULL)}; + SLresult result{slCreateEngine(&mEngineObj, 0, nullptr, 0, nullptr, nullptr)}; PRINTERR(result, "slCreateEngine"); if(SL_RESULT_SUCCESS == result) { @@ -318,7 +319,7 @@ ALCenum OpenSLPlayback::open(const ALCchar *name) } if(SL_RESULT_SUCCESS == result) { - result = VCALL(mEngine,CreateOutputMix)(&mOutputMix, 0, NULL, NULL); + result = VCALL(mEngine,CreateOutputMix)(&mOutputMix, 0, nullptr, nullptr); PRINTERR(result, "engine->CreateOutputMix"); } if(SL_RESULT_SUCCESS == result) @@ -331,12 +332,12 @@ ALCenum OpenSLPlayback::open(const ALCchar *name) { if(mOutputMix) VCALL0(mOutputMix,Destroy)(); - mOutputMix = NULL; + mOutputMix = nullptr; if(mEngineObj) VCALL0(mEngineObj,Destroy)(); - mEngineObj = NULL; - mEngine = NULL; + mEngineObj = nullptr; + mEngine = nullptr; return ALC_INVALID_VALUE; } @@ -358,7 +359,7 @@ ALCboolean OpenSLPlayback::reset() if(mBufferQueueObj) VCALL0(mBufferQueueObj,Destroy)(); - mBufferQueueObj = NULL; + mBufferQueueObj = nullptr; mRing = nullptr; @@ -408,21 +409,21 @@ ALCboolean OpenSLPlayback::reset() //AudioManager audMgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE); strobj = JCALL(env,GetStaticObjectField)(ctx_cls, ctx_audsvc); jobject audMgr = JCALL(env,CallObjectMethod)(jctx, ctx_getSysSvc, strobj); - strchars = JCALL(env,GetStringUTFChars)(strobj, NULL); + strchars = JCALL(env,GetStringUTFChars)(strobj, nullptr); TRACE("Context.getSystemService(%s) = %p\n", strchars, audMgr); JCALL(env,ReleaseStringUTFChars)(strobj, strchars); //String srateStr = audMgr.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE); strobj = JCALL(env,GetStaticObjectField)(audmgr_cls, audmgr_prop_out_srate); jstring srateStr = JCALL(env,CallObjectMethod)(audMgr, audmgr_getproperty, strobj); - strchars = JCALL(env,GetStringUTFChars)(strobj, NULL); + strchars = JCALL(env,GetStringUTFChars)(strobj, nullptr); TRACE("audMgr.getProperty(%s) = %p\n", strchars, srateStr); JCALL(env,ReleaseStringUTFChars)(strobj, strchars); //int sampleRate = Integer.parseInt(srateStr); sampleRate = JCALL(env,CallStaticIntMethod)(int_cls, int_parseint, srateStr); - strchars = JCALL(env,GetStringUTFChars)(srateStr, NULL); + strchars = JCALL(env,GetStringUTFChars)(srateStr, nullptr); TRACE("Got system sample rate %uhz (%s)\n", sampleRate, strchars); JCALL(env,ReleaseStringUTFChars)(srateStr, strchars); @@ -478,7 +479,7 @@ ALCboolean OpenSLPlayback::reset() loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; loc_outmix.outputMix = mOutputMix; audioSnk.pLocator = &loc_outmix; - audioSnk.pFormat = NULL; + audioSnk.pFormat = nullptr; ids[0] = SL_IID_ANDROIDSIMPLEBUFFERQUEUE; @@ -513,11 +514,12 @@ ALCboolean OpenSLPlayback::reset() } if(SL_RESULT_SUCCESS == result) { - mRing = CreateRingBuffer(mDevice->NumUpdates, mFrameSize*mDevice->UpdateSize, true); - if(!mRing) - { - ERR("Out of memory allocating ring buffer %ux%u %u\n", mDevice->UpdateSize, - mDevice->NumUpdates, mFrameSize); + try { + mRing = CreateRingBuffer(mDevice->NumUpdates, mFrameSize*mDevice->UpdateSize, true); + } + catch(std::exception& e) { + ERR("Failed allocating ring buffer %ux%ux%u: %s\n", mDevice->UpdateSize, + mDevice->NumUpdates, mFrameSize, e.what()); result = SL_RESULT_MEMORY_FAILURE; } } @@ -526,7 +528,7 @@ ALCboolean OpenSLPlayback::reset() { if(mBufferQueueObj) VCALL0(mBufferQueueObj,Destroy)(); - mBufferQueueObj = NULL; + mBufferQueueObj = nullptr; return ALC_FALSE; } @@ -589,7 +591,7 @@ void OpenSLPlayback::stop() } if(SL_RESULT_SUCCESS == result) { - result = VCALL(bufferQueue,RegisterCallback)(NULL, NULL); + result = VCALL(bufferQueue,RegisterCallback)(nullptr, nullptr); PRINTERR(result, "bufferQueue->RegisterCallback"); } if(SL_RESULT_SUCCESS == result) @@ -671,19 +673,12 @@ void OpenSLCapture::process(SLAndroidSimpleBufferQueueItf UNUSED(bq)) ALCenum OpenSLCapture::open(const ALCchar* name) { - SLDataLocator_AndroidSimpleBufferQueue loc_bq; - SLAndroidSimpleBufferQueueItf bufferQueue; - SLDataLocator_IODevice loc_dev; - SLDataSource audioSrc; - SLDataSink audioSnk; - SLresult result; - if(!name) name = opensl_device; else if(strcmp(name, opensl_device) != 0) return ALC_INVALID_VALUE; - result = slCreateEngine(&mEngineObj, 0, NULL, 0, NULL, NULL); + SLresult result{slCreateEngine(&mEngineObj, 0, nullptr, 0, nullptr, nullptr)}; PRINTERR(result, "slCreateEngine"); if(SL_RESULT_SUCCESS == result) { @@ -697,58 +692,68 @@ ALCenum OpenSLCapture::open(const ALCchar* name) } if(SL_RESULT_SUCCESS == result) { + mFrameSize = mDevice->frameSizeFromFmt(); /* Ensure the total length is at least 100ms */ ALsizei length{maxi(mDevice->NumUpdates*mDevice->UpdateSize, mDevice->Frequency/10)}; /* Ensure the per-chunk length is at least 10ms, and no more than 50ms. */ ALsizei update_len{clampi(mDevice->NumUpdates*mDevice->UpdateSize / 3, mDevice->Frequency/100, mDevice->Frequency/100*5)}; + ALsizei num_updates{(length+update_len-1) / update_len}; - mDevice->UpdateSize = update_len; - mDevice->NumUpdates = (length+update_len-1) / update_len; + try { + mRing = CreateRingBuffer(num_updates, update_len*mFrameSize, false); - mFrameSize = mDevice->frameSizeFromFmt(); + mDevice->UpdateSize = update_len; + mDevice->NumUpdates = mRing->writeSpace(); + } + catch(std::exception& e) { + ERR("Failed to allocate ring buffer: %s\n", e.what()); + result = SL_RESULT_MEMORY_FAILURE; + } } - loc_dev.locatorType = SL_DATALOCATOR_IODEVICE; - loc_dev.deviceType = SL_IODEVICE_AUDIOINPUT; - loc_dev.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT; - loc_dev.device = NULL; + if(SL_RESULT_SUCCESS == result) + { + const SLInterfaceID ids[2] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION }; + const SLboolean reqs[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_FALSE }; + + SLDataLocator_IODevice loc_dev{}; + loc_dev.locatorType = SL_DATALOCATOR_IODEVICE; + loc_dev.deviceType = SL_IODEVICE_AUDIOINPUT; + loc_dev.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT; + loc_dev.device = nullptr; - audioSrc.pLocator = &loc_dev; - audioSrc.pFormat = NULL; + SLDataSource audioSrc{}; + audioSrc.pLocator = &loc_dev; + audioSrc.pFormat = nullptr; - loc_bq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; - loc_bq.numBuffers = mDevice->NumUpdates; + SLDataLocator_AndroidSimpleBufferQueue loc_bq{}; + loc_bq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; + loc_bq.numBuffers = mDevice->NumUpdates; #ifdef SL_DATAFORMAT_PCM_EX - SLDataFormat_PCM_EX format_pcm; - format_pcm.formatType = SL_DATAFORMAT_PCM_EX; - format_pcm.numChannels = mDevice->channelsFromFmt(); - format_pcm.sampleRate = mDevice->Frequency * 1000; - format_pcm.bitsPerSample = mDevice->bytesFromFmt() * 8; - format_pcm.containerSize = format_pcm.bitsPerSample; - format_pcm.channelMask = GetChannelMask(mDevice->FmtChans); - format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN : - SL_BYTEORDER_BIGENDIAN; - format_pcm.representation = GetTypeRepresentation(mDevice->FmtType); + SLDataFormat_PCM_EX format_pcm{}; + format_pcm.formatType = SL_DATAFORMAT_PCM_EX; + format_pcm.numChannels = mDevice->channelsFromFmt(); + format_pcm.sampleRate = mDevice->Frequency * 1000; + format_pcm.bitsPerSample = mDevice->bytesFromFmt() * 8; + format_pcm.containerSize = format_pcm.bitsPerSample; + format_pcm.channelMask = GetChannelMask(mDevice->FmtChans); + format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN : SL_BYTEORDER_BIGENDIAN; + format_pcm.representation = GetTypeRepresentation(mDevice->FmtType); #else - SLDataFormat_PCM format_pcm; - format_pcm.formatType = SL_DATAFORMAT_PCM; - format_pcm.numChannels = mDevice->channelsFromFmt(); - format_pcm.samplesPerSec = mDevice->Frequency * 1000; - format_pcm.bitsPerSample = mDevice->bytesFromFmt() * 8; - format_pcm.containerSize = format_pcm.bitsPerSample; - format_pcm.channelMask = GetChannelMask(mDevice->FmtChans); - format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN : - SL_BYTEORDER_BIGENDIAN; + SLDataFormat_PCM format_pcm{}; + format_pcm.formatType = SL_DATAFORMAT_PCM; + format_pcm.numChannels = mDevice->channelsFromFmt(); + format_pcm.samplesPerSec = mDevice->Frequency * 1000; + format_pcm.bitsPerSample = mDevice->bytesFromFmt() * 8; + format_pcm.containerSize = format_pcm.bitsPerSample; + format_pcm.channelMask = GetChannelMask(mDevice->FmtChans); + format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN : SL_BYTEORDER_BIGENDIAN; #endif - audioSnk.pLocator = &loc_bq; - audioSnk.pFormat = &format_pcm; - - if(SL_RESULT_SUCCESS == result) - { - const SLInterfaceID ids[2] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION }; - const SLboolean reqs[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_FALSE }; + SLDataSink audioSnk{}; + audioSnk.pLocator = &loc_bq; + audioSnk.pFormat = &format_pcm; result = VCALL(mEngine,CreateAudioRecorder)(&mRecordObj, &audioSrc, &audioSnk, COUNTOF(ids), ids, reqs); @@ -777,10 +782,9 @@ ALCenum OpenSLCapture::open(const ALCchar* name) PRINTERR(result, "recordObj->Realize"); } + SLAndroidSimpleBufferQueueItf bufferQueue; if(SL_RESULT_SUCCESS == result) { - mRing = CreateRingBuffer(mDevice->NumUpdates, mDevice->UpdateSize*mFrameSize, false); - result = VCALL(mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bufferQueue); PRINTERR(result, "recordObj->GetInterface"); } @@ -791,16 +795,15 @@ ALCenum OpenSLCapture::open(const ALCchar* name) } if(SL_RESULT_SUCCESS == result) { - ALsizei chunk_size = mDevice->UpdateSize * mFrameSize; - size_t i; + const ALuint chunk_size{mDevice->UpdateSize * mFrameSize}; auto data = mRing->getWriteVector(); - for(i = 0;i < data.first.len && SL_RESULT_SUCCESS == result;i++) + for(size_t i{0u};i < data.first.len && SL_RESULT_SUCCESS == result;i++) { result = VCALL(bufferQueue,Enqueue)(data.first.buf + chunk_size*i, chunk_size); PRINTERR(result, "bufferQueue->Enqueue"); } - for(i = 0;i < data.second.len && SL_RESULT_SUCCESS == result;i++) + for(size_t i{0u};i < data.second.len && SL_RESULT_SUCCESS == result;i++) { result = VCALL(bufferQueue,Enqueue)(data.second.buf + chunk_size*i, chunk_size); PRINTERR(result, "bufferQueue->Enqueue"); |