diff options
Diffstat (limited to 'externals/oboe/src/opensles/AudioOutputStreamOpenSLES.cpp')
| -rw-r--r-- | externals/oboe/src/opensles/AudioOutputStreamOpenSLES.cpp | 457 |
1 files changed, 0 insertions, 457 deletions
diff --git a/externals/oboe/src/opensles/AudioOutputStreamOpenSLES.cpp b/externals/oboe/src/opensles/AudioOutputStreamOpenSLES.cpp deleted file mode 100644 index 1b94885711..0000000000 --- a/externals/oboe/src/opensles/AudioOutputStreamOpenSLES.cpp +++ /dev/null @@ -1,457 +0,0 @@ -/* - * Copyright 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <cassert> - -#include "common/OboeDebug.h" -#include "oboe/AudioClock.h" -#include "oboe/AudioStreamBuilder.h" -#include "AudioOutputStreamOpenSLES.h" -#include "AudioStreamOpenSLES.h" -#include "OpenSLESUtilities.h" -#include "OutputMixerOpenSLES.h" - -using namespace oboe; - -static SLuint32 OpenSLES_convertOutputUsage(Usage oboeUsage) { - SLuint32 openslStream; - switch(oboeUsage) { - case Usage::Media: - case Usage::Game: - openslStream = SL_ANDROID_STREAM_MEDIA; - break; - case Usage::VoiceCommunication: - case Usage::VoiceCommunicationSignalling: - openslStream = SL_ANDROID_STREAM_VOICE; - break; - case Usage::Alarm: - openslStream = SL_ANDROID_STREAM_ALARM; - break; - case Usage::Notification: - case Usage::NotificationEvent: - openslStream = SL_ANDROID_STREAM_NOTIFICATION; - break; - case Usage::NotificationRingtone: - openslStream = SL_ANDROID_STREAM_RING; - break; - case Usage::AssistanceAccessibility: - case Usage::AssistanceNavigationGuidance: - case Usage::AssistanceSonification: - case Usage::Assistant: - default: - openslStream = SL_ANDROID_STREAM_SYSTEM; - break; - } - return openslStream; -} - -AudioOutputStreamOpenSLES::AudioOutputStreamOpenSLES(const AudioStreamBuilder &builder) - : AudioStreamOpenSLES(builder) { -} - -// These will wind up in <SLES/OpenSLES_Android.h> -constexpr int SL_ANDROID_SPEAKER_STEREO = (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT); - -constexpr int SL_ANDROID_SPEAKER_QUAD = (SL_ANDROID_SPEAKER_STEREO - | SL_SPEAKER_BACK_LEFT | SL_SPEAKER_BACK_RIGHT); - -constexpr int SL_ANDROID_SPEAKER_5DOT1 = (SL_ANDROID_SPEAKER_QUAD - | SL_SPEAKER_FRONT_CENTER | SL_SPEAKER_LOW_FREQUENCY); - -constexpr int SL_ANDROID_SPEAKER_7DOT1 = (SL_ANDROID_SPEAKER_5DOT1 | SL_SPEAKER_SIDE_LEFT - | SL_SPEAKER_SIDE_RIGHT); - -SLuint32 AudioOutputStreamOpenSLES::channelCountToChannelMask(int channelCount) const { - SLuint32 channelMask = 0; - - switch (channelCount) { - case 1: - channelMask = SL_SPEAKER_FRONT_CENTER; - break; - - case 2: - channelMask = SL_ANDROID_SPEAKER_STEREO; - break; - - case 4: // Quad - channelMask = SL_ANDROID_SPEAKER_QUAD; - break; - - case 6: // 5.1 - channelMask = SL_ANDROID_SPEAKER_5DOT1; - break; - - case 8: // 7.1 - channelMask = SL_ANDROID_SPEAKER_7DOT1; - break; - - default: - channelMask = channelCountToChannelMaskDefault(channelCount); - break; - } - return channelMask; -} - -Result AudioOutputStreamOpenSLES::open() { - logUnsupportedAttributes(); - - SLAndroidConfigurationItf configItf = nullptr; - - - if (getSdkVersion() < __ANDROID_API_L__ && mFormat == AudioFormat::Float){ - // TODO: Allow floating point format on API <21 using float->int16 converter - return Result::ErrorInvalidFormat; - } - - // If audio format is unspecified then choose a suitable default. - // API 21+: FLOAT - // API <21: INT16 - if (mFormat == AudioFormat::Unspecified){ - mFormat = (getSdkVersion() < __ANDROID_API_L__) ? - AudioFormat::I16 : AudioFormat::Float; - } - - Result oboeResult = AudioStreamOpenSLES::open(); - if (Result::OK != oboeResult) return oboeResult; - - SLresult result = OutputMixerOpenSL::getInstance().open(); - if (SL_RESULT_SUCCESS != result) { - AudioStreamOpenSLES::close(); - return Result::ErrorInternal; - } - - SLuint32 bitsPerSample = static_cast<SLuint32>(getBytesPerSample() * kBitsPerByte); - - // configure audio source - mBufferQueueLength = calculateOptimalBufferQueueLength(); - SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { - SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, // locatorType - static_cast<SLuint32>(mBufferQueueLength)}; // numBuffers - - // Define the audio data format. - SLDataFormat_PCM format_pcm = { - SL_DATAFORMAT_PCM, // formatType - static_cast<SLuint32>(mChannelCount), // numChannels - static_cast<SLuint32>(mSampleRate * kMillisPerSecond), // milliSamplesPerSec - bitsPerSample, // mBitsPerSample - bitsPerSample, // containerSize; - channelCountToChannelMask(mChannelCount), // channelMask - getDefaultByteOrder(), - }; - - SLDataSource audioSrc = {&loc_bufq, &format_pcm}; - - /** - * API 21 (Lollipop) introduced support for floating-point data representation and an extended - * data format type: SLAndroidDataFormat_PCM_EX. If running on API 21+ use this newer format - * type, creating it from our original format. - */ - SLAndroidDataFormat_PCM_EX format_pcm_ex; - if (getSdkVersion() >= __ANDROID_API_L__) { - SLuint32 representation = OpenSLES_ConvertFormatToRepresentation(getFormat()); - // Fill in the format structure. - format_pcm_ex = OpenSLES_createExtendedFormat(format_pcm, representation); - // Use in place of the previous format. - audioSrc.pFormat = &format_pcm_ex; - } - - result = OutputMixerOpenSL::getInstance().createAudioPlayer(&mObjectInterface, - &audioSrc); - if (SL_RESULT_SUCCESS != result) { - LOGE("createAudioPlayer() result:%s", getSLErrStr(result)); - goto error; - } - - // Configure the stream. - result = (*mObjectInterface)->GetInterface(mObjectInterface, - EngineOpenSLES::getInstance().getIidAndroidConfiguration(), - (void *)&configItf); - if (SL_RESULT_SUCCESS != result) { - LOGW("%s() GetInterface(SL_IID_ANDROIDCONFIGURATION) failed with %s", - __func__, getSLErrStr(result)); - } else { - result = configurePerformanceMode(configItf); - if (SL_RESULT_SUCCESS != result) { - goto error; - } - - SLuint32 presetValue = OpenSLES_convertOutputUsage(getUsage()); - result = (*configItf)->SetConfiguration(configItf, - SL_ANDROID_KEY_STREAM_TYPE, - &presetValue, - sizeof(presetValue)); - if (SL_RESULT_SUCCESS != result) { - goto error; - } - } - - result = (*mObjectInterface)->Realize(mObjectInterface, SL_BOOLEAN_FALSE); - if (SL_RESULT_SUCCESS != result) { - LOGE("Realize player object result:%s", getSLErrStr(result)); - goto error; - } - - result = (*mObjectInterface)->GetInterface(mObjectInterface, - EngineOpenSLES::getInstance().getIidPlay(), - &mPlayInterface); - if (SL_RESULT_SUCCESS != result) { - LOGE("GetInterface PLAY result:%s", getSLErrStr(result)); - goto error; - } - - result = finishCommonOpen(configItf); - if (SL_RESULT_SUCCESS != result) { - goto error; - } - - setState(StreamState::Open); - return Result::OK; - -error: - close(); // Clean up various OpenSL objects and prevent resource leaks. - return Result::ErrorInternal; // TODO convert error from SLES to OBOE -} - -Result AudioOutputStreamOpenSLES::onAfterDestroy() { - OutputMixerOpenSL::getInstance().close(); - return Result::OK; -} - -Result AudioOutputStreamOpenSLES::close() { - LOGD("AudioOutputStreamOpenSLES::%s()", __func__); - std::lock_guard<std::mutex> lock(mLock); - Result result = Result::OK; - if (getState() == StreamState::Closed) { - result = Result::ErrorClosed; - } else { - (void) requestPause_l(); - if (OboeGlobals::areWorkaroundsEnabled()) { - sleepBeforeClose(); - } - // invalidate any interfaces - mPlayInterface = nullptr; - result = AudioStreamOpenSLES::close_l(); - } - return result; -} - -Result AudioOutputStreamOpenSLES::setPlayState_l(SLuint32 newState) { - LOGD("AudioOutputStreamOpenSLES::%s(%d) called", __func__, newState); - Result result = Result::OK; - - if (mPlayInterface == nullptr){ - LOGE("AudioOutputStreamOpenSLES::%s() mPlayInterface is null", __func__); - return Result::ErrorInvalidState; - } - - SLresult slResult = (*mPlayInterface)->SetPlayState(mPlayInterface, newState); - if (SL_RESULT_SUCCESS != slResult) { - LOGW("AudioOutputStreamOpenSLES(): %s() returned %s", __func__, getSLErrStr(slResult)); - result = Result::ErrorInternal; // TODO convert slResult to Result::Error - } - return result; -} - -Result AudioOutputStreamOpenSLES::requestStart() { - LOGD("AudioOutputStreamOpenSLES::%s() called", __func__); - - mLock.lock(); - StreamState initialState = getState(); - switch (initialState) { - case StreamState::Starting: - case StreamState::Started: - mLock.unlock(); - return Result::OK; - case StreamState::Closed: - mLock.unlock(); - return Result::ErrorClosed; - default: - break; - } - - // We use a callback if the user requests one - // OR if we have an internal callback to read the blocking IO buffer. - setDataCallbackEnabled(true); - - setState(StreamState::Starting); - closePerformanceHint(); - - if (getBufferDepth(mSimpleBufferQueueInterface) == 0) { - // Enqueue the first buffer if needed to start the streaming. - // We may need to stop the current stream. - bool shouldStopStream = processBufferCallback(mSimpleBufferQueueInterface); - if (shouldStopStream) { - LOGD("Stopping the current stream."); - if (requestStop_l() != Result::OK) { - LOGW("Failed to flush the stream. Error %s", convertToText(flush())); - } - setState(initialState); - mLock.unlock(); - return Result::ErrorClosed; - } - } - - Result result = setPlayState_l(SL_PLAYSTATE_PLAYING); - if (result == Result::OK) { - setState(StreamState::Started); - mLock.unlock(); - } else { - setState(initialState); - mLock.unlock(); - } - return result; -} - -Result AudioOutputStreamOpenSLES::requestPause() { - LOGD("AudioOutputStreamOpenSLES::%s() called", __func__); - std::lock_guard<std::mutex> lock(mLock); - return requestPause_l(); -} - -// Call under mLock -Result AudioOutputStreamOpenSLES::requestPause_l() { - StreamState initialState = getState(); - switch (initialState) { - case StreamState::Pausing: - case StreamState::Paused: - return Result::OK; - case StreamState::Uninitialized: - case StreamState::Closed: - return Result::ErrorClosed; - default: - break; - } - - setState(StreamState::Pausing); - Result result = setPlayState_l(SL_PLAYSTATE_PAUSED); - if (result == Result::OK) { - // Note that OpenSL ES does NOT reset its millisecond position when OUTPUT is paused. - int64_t framesWritten = getFramesWritten(); - if (framesWritten >= 0) { - setFramesRead(framesWritten); - } - setState(StreamState::Paused); - } else { - setState(initialState); - } - return result; -} - -/** - * Flush/clear the queue buffers - */ -Result AudioOutputStreamOpenSLES::requestFlush() { - std::lock_guard<std::mutex> lock(mLock); - return requestFlush_l(); -} - -Result AudioOutputStreamOpenSLES::requestFlush_l() { - LOGD("AudioOutputStreamOpenSLES::%s() called", __func__); - if (getState() == StreamState::Closed) { - return Result::ErrorClosed; - } - - Result result = Result::OK; - if (mPlayInterface == nullptr || mSimpleBufferQueueInterface == nullptr) { - result = Result::ErrorInvalidState; - } else { - SLresult slResult = (*mSimpleBufferQueueInterface)->Clear(mSimpleBufferQueueInterface); - if (slResult != SL_RESULT_SUCCESS){ - LOGW("Failed to clear buffer queue. OpenSLES error: %s", getSLErrStr(slResult)); - result = Result::ErrorInternal; - } - } - return result; -} - -Result AudioOutputStreamOpenSLES::requestStop() { - std::lock_guard<std::mutex> lock(mLock); - return requestStop_l(); -} - -Result AudioOutputStreamOpenSLES::requestStop_l() { - StreamState initialState = getState(); - LOGD("AudioOutputStreamOpenSLES::%s() called, initialState = %d", __func__, initialState); - switch (initialState) { - case StreamState::Stopping: - case StreamState::Stopped: - return Result::OK; - case StreamState::Uninitialized: - case StreamState::Closed: - return Result::ErrorClosed; - default: - break; - } - - setState(StreamState::Stopping); - - Result result = setPlayState_l(SL_PLAYSTATE_STOPPED); - if (result == Result::OK) { - - // Also clear the buffer queue so the old data won't be played if the stream is restarted. - // Call the _l function that expects to already be under a lock. - if (requestFlush_l() != Result::OK) { - LOGW("Failed to flush the stream. Error %s", convertToText(flush())); - } - - mPositionMillis.reset32(); // OpenSL ES resets its millisecond position when stopped. - int64_t framesWritten = getFramesWritten(); - if (framesWritten >= 0) { - setFramesRead(framesWritten); - } - setState(StreamState::Stopped); - } else { - setState(initialState); - } - return result; -} - -void AudioOutputStreamOpenSLES::setFramesRead(int64_t framesRead) { - int64_t millisWritten = framesRead * kMillisPerSecond / getSampleRate(); - mPositionMillis.set(millisWritten); -} - -void AudioOutputStreamOpenSLES::updateFramesRead() { - if (usingFIFO()) { - AudioStreamBuffered::updateFramesRead(); - } else { - mFramesRead = getFramesProcessedByServer(); - } -} - -Result AudioOutputStreamOpenSLES::updateServiceFrameCounter() { - Result result = Result::OK; - // Avoid deadlock if another thread is trying to stop or close this stream - // and this is being called from a callback. - if (mLock.try_lock()) { - - if (mPlayInterface == nullptr) { - mLock.unlock(); - return Result::ErrorNull; - } - SLmillisecond msec = 0; - SLresult slResult = (*mPlayInterface)->GetPosition(mPlayInterface, &msec); - if (SL_RESULT_SUCCESS != slResult) { - LOGW("%s(): GetPosition() returned %s", __func__, getSLErrStr(slResult)); - // set result based on SLresult - result = Result::ErrorInternal; - } else { - mPositionMillis.update32(msec); - } - mLock.unlock(); - } - return result; -} |
