aboutsummaryrefslogtreecommitdiff
path: root/externals/oboe/src/opensles/AudioOutputStreamOpenSLES.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'externals/oboe/src/opensles/AudioOutputStreamOpenSLES.cpp')
-rw-r--r--externals/oboe/src/opensles/AudioOutputStreamOpenSLES.cpp457
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;
-}