1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2016 The Android Open Source Project 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 5cb93a386Sopenharmony_ci * you may not use this file except in compliance with the License. 6cb93a386Sopenharmony_ci * You may obtain a copy of the License at 7cb93a386Sopenharmony_ci * 8cb93a386Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 9cb93a386Sopenharmony_ci * 10cb93a386Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 11cb93a386Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 12cb93a386Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cb93a386Sopenharmony_ci * See the License for the specific language governing permissions and 14cb93a386Sopenharmony_ci * limitations under the License. 15cb93a386Sopenharmony_ci */ 16cb93a386Sopenharmony_ci 17cb93a386Sopenharmony_ci#include <sys/types.h> 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ci#include "aaudio/AudioStreamAAudio.h" 20cb93a386Sopenharmony_ci#include "FilterAudioStream.h" 21cb93a386Sopenharmony_ci#include "OboeDebug.h" 22cb93a386Sopenharmony_ci#include "oboe/Oboe.h" 23cb93a386Sopenharmony_ci#include "oboe/AudioStreamBuilder.h" 24cb93a386Sopenharmony_ci#include "opensles/AudioInputStreamOpenSLES.h" 25cb93a386Sopenharmony_ci#include "opensles/AudioOutputStreamOpenSLES.h" 26cb93a386Sopenharmony_ci#include "opensles/AudioStreamOpenSLES.h" 27cb93a386Sopenharmony_ci#include "QuirksManager.h" 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_cibool oboe::OboeGlobals::mWorkaroundsEnabled = true; 30cb93a386Sopenharmony_ci 31cb93a386Sopenharmony_cinamespace oboe { 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_ci/** 34cb93a386Sopenharmony_ci * The following default values are used when oboe does not have any better way of determining the optimal values 35cb93a386Sopenharmony_ci * for an audio stream. This can happen when: 36cb93a386Sopenharmony_ci * 37cb93a386Sopenharmony_ci * - Client is creating a stream on API < 26 (OpenSLES) but has not supplied the optimal sample 38cb93a386Sopenharmony_ci * rate and/or frames per burst 39cb93a386Sopenharmony_ci * - Client is creating a stream on API 16 (OpenSLES) where AudioManager.PROPERTY_OUTPUT_* values 40cb93a386Sopenharmony_ci * are not available 41cb93a386Sopenharmony_ci */ 42cb93a386Sopenharmony_ciint32_t DefaultStreamValues::SampleRate = 48000; // Common rate for mobile audio and video 43cb93a386Sopenharmony_ciint32_t DefaultStreamValues::FramesPerBurst = 192; // 4 msec at 48000 Hz 44cb93a386Sopenharmony_ciint32_t DefaultStreamValues::ChannelCount = 2; // Stereo 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_ciconstexpr int kBufferSizeInBurstsForLowLatencyStreams = 2; 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_ci#ifndef OBOE_ENABLE_AAUDIO 49cb93a386Sopenharmony_ci// Set OBOE_ENABLE_AAUDIO to 0 if you want to disable the AAudio API. 50cb93a386Sopenharmony_ci// This might be useful if you want to force all the unit tests to use OpenSL ES. 51cb93a386Sopenharmony_ci#define OBOE_ENABLE_AAUDIO 1 52cb93a386Sopenharmony_ci#endif 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_cibool AudioStreamBuilder::isAAudioSupported() { 55cb93a386Sopenharmony_ci return AudioStreamAAudio::isSupported() && OBOE_ENABLE_AAUDIO; 56cb93a386Sopenharmony_ci} 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_cibool AudioStreamBuilder::isAAudioRecommended() { 59cb93a386Sopenharmony_ci // See https://github.com/google/oboe/issues/40, 60cb93a386Sopenharmony_ci // AAudio may not be stable on Android O, depending on how it is used. 61cb93a386Sopenharmony_ci // To be safe, use AAudio only on O_MR1 and above. 62cb93a386Sopenharmony_ci return (getSdkVersion() >= __ANDROID_API_O_MR1__) && isAAudioSupported(); 63cb93a386Sopenharmony_ci} 64cb93a386Sopenharmony_ci 65cb93a386Sopenharmony_ciAudioStream *AudioStreamBuilder::build() { 66cb93a386Sopenharmony_ci AudioStream *stream = nullptr; 67cb93a386Sopenharmony_ci if (isAAudioRecommended() && mAudioApi != AudioApi::OpenSLES) { 68cb93a386Sopenharmony_ci stream = new AudioStreamAAudio(*this); 69cb93a386Sopenharmony_ci } else if (isAAudioSupported() && mAudioApi == AudioApi::AAudio) { 70cb93a386Sopenharmony_ci stream = new AudioStreamAAudio(*this); 71cb93a386Sopenharmony_ci LOGE("Creating AAudio stream on 8.0 because it was specified. This is error prone."); 72cb93a386Sopenharmony_ci } else { 73cb93a386Sopenharmony_ci if (getDirection() == oboe::Direction::Output) { 74cb93a386Sopenharmony_ci stream = new AudioOutputStreamOpenSLES(*this); 75cb93a386Sopenharmony_ci } else if (getDirection() == oboe::Direction::Input) { 76cb93a386Sopenharmony_ci stream = new AudioInputStreamOpenSLES(*this); 77cb93a386Sopenharmony_ci } 78cb93a386Sopenharmony_ci } 79cb93a386Sopenharmony_ci return stream; 80cb93a386Sopenharmony_ci} 81cb93a386Sopenharmony_ci 82cb93a386Sopenharmony_cibool AudioStreamBuilder::isCompatible(AudioStreamBase &other) { 83cb93a386Sopenharmony_ci return (getSampleRate() == oboe::Unspecified || getSampleRate() == other.getSampleRate()) 84cb93a386Sopenharmony_ci && (getFormat() == (AudioFormat)oboe::Unspecified || getFormat() == other.getFormat()) 85cb93a386Sopenharmony_ci && (getFramesPerCallback() == oboe::Unspecified || getFramesPerCallback() == other.getFramesPerCallback()) 86cb93a386Sopenharmony_ci && (getChannelCount() == oboe::Unspecified || getChannelCount() == other.getChannelCount()); 87cb93a386Sopenharmony_ci} 88cb93a386Sopenharmony_ci 89cb93a386Sopenharmony_ciResult AudioStreamBuilder::openStream(AudioStream **streamPP) { 90cb93a386Sopenharmony_ci auto result = isValidConfig(); 91cb93a386Sopenharmony_ci if (result != Result::OK) { 92cb93a386Sopenharmony_ci return result; 93cb93a386Sopenharmony_ci } 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_ci LOGI("%s() %s -------- %s --------", 96cb93a386Sopenharmony_ci __func__, getDirection() == Direction::Input ? "INPUT" : "OUTPUT", getVersionText()); 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ci if (streamPP == nullptr) { 99cb93a386Sopenharmony_ci return Result::ErrorNull; 100cb93a386Sopenharmony_ci } 101cb93a386Sopenharmony_ci *streamPP = nullptr; 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_ci AudioStream *streamP = nullptr; 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_ci // Maybe make a FilterInputStream. 106cb93a386Sopenharmony_ci AudioStreamBuilder childBuilder(*this); 107cb93a386Sopenharmony_ci // Check need for conversion and modify childBuilder for optimal stream. 108cb93a386Sopenharmony_ci bool conversionNeeded = QuirksManager::getInstance().isConversionNeeded(*this, childBuilder); 109cb93a386Sopenharmony_ci // Do we need to make a child stream and convert. 110cb93a386Sopenharmony_ci if (conversionNeeded) { 111cb93a386Sopenharmony_ci AudioStream *tempStream; 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci result = childBuilder.openStream(&tempStream); 114cb93a386Sopenharmony_ci if (result != Result::OK) { 115cb93a386Sopenharmony_ci return result; 116cb93a386Sopenharmony_ci } 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_ci if (isCompatible(*tempStream)) { 119cb93a386Sopenharmony_ci // The child stream would work as the requested stream so we can just use it directly. 120cb93a386Sopenharmony_ci *streamPP = tempStream; 121cb93a386Sopenharmony_ci return result; 122cb93a386Sopenharmony_ci } else { 123cb93a386Sopenharmony_ci AudioStreamBuilder parentBuilder = *this; 124cb93a386Sopenharmony_ci // Build a stream that is as close as possible to the childStream. 125cb93a386Sopenharmony_ci if (getFormat() == oboe::AudioFormat::Unspecified) { 126cb93a386Sopenharmony_ci parentBuilder.setFormat(tempStream->getFormat()); 127cb93a386Sopenharmony_ci } 128cb93a386Sopenharmony_ci if (getChannelCount() == oboe::Unspecified) { 129cb93a386Sopenharmony_ci parentBuilder.setChannelCount(tempStream->getChannelCount()); 130cb93a386Sopenharmony_ci } 131cb93a386Sopenharmony_ci if (getSampleRate() == oboe::Unspecified) { 132cb93a386Sopenharmony_ci parentBuilder.setSampleRate(tempStream->getSampleRate()); 133cb93a386Sopenharmony_ci } 134cb93a386Sopenharmony_ci if (getFramesPerCallback() == oboe::Unspecified) { 135cb93a386Sopenharmony_ci parentBuilder.setFramesPerCallback(tempStream->getFramesPerCallback()); 136cb93a386Sopenharmony_ci } 137cb93a386Sopenharmony_ci 138cb93a386Sopenharmony_ci // Use childStream in a FilterAudioStream. 139cb93a386Sopenharmony_ci LOGI("%s() create a FilterAudioStream for data conversion.", __func__); 140cb93a386Sopenharmony_ci FilterAudioStream *filterStream = new FilterAudioStream(parentBuilder, tempStream); 141cb93a386Sopenharmony_ci result = filterStream->configureFlowGraph(); 142cb93a386Sopenharmony_ci if (result != Result::OK) { 143cb93a386Sopenharmony_ci filterStream->close(); 144cb93a386Sopenharmony_ci delete filterStream; 145cb93a386Sopenharmony_ci // Just open streamP the old way. 146cb93a386Sopenharmony_ci } else { 147cb93a386Sopenharmony_ci streamP = static_cast<AudioStream *>(filterStream); 148cb93a386Sopenharmony_ci } 149cb93a386Sopenharmony_ci } 150cb93a386Sopenharmony_ci } 151cb93a386Sopenharmony_ci 152cb93a386Sopenharmony_ci if (streamP == nullptr) { 153cb93a386Sopenharmony_ci streamP = build(); 154cb93a386Sopenharmony_ci if (streamP == nullptr) { 155cb93a386Sopenharmony_ci return Result::ErrorNull; 156cb93a386Sopenharmony_ci } 157cb93a386Sopenharmony_ci } 158cb93a386Sopenharmony_ci 159cb93a386Sopenharmony_ci result = streamP->open(); // TODO review API 160cb93a386Sopenharmony_ci if (result == Result::OK) { 161cb93a386Sopenharmony_ci 162cb93a386Sopenharmony_ci int32_t optimalBufferSize = -1; 163cb93a386Sopenharmony_ci // Use a reasonable default buffer size. 164cb93a386Sopenharmony_ci if (streamP->getDirection() == Direction::Input) { 165cb93a386Sopenharmony_ci // For input, small size does not improve latency because the stream is usually 166cb93a386Sopenharmony_ci // run close to empty. And a low size can result in XRuns so always use the maximum. 167cb93a386Sopenharmony_ci optimalBufferSize = streamP->getBufferCapacityInFrames(); 168cb93a386Sopenharmony_ci } else if (streamP->getPerformanceMode() == PerformanceMode::LowLatency 169cb93a386Sopenharmony_ci && streamP->getDirection() == Direction::Output) { // Output check is redundant. 170cb93a386Sopenharmony_ci optimalBufferSize = streamP->getFramesPerBurst() * 171cb93a386Sopenharmony_ci kBufferSizeInBurstsForLowLatencyStreams; 172cb93a386Sopenharmony_ci } 173cb93a386Sopenharmony_ci if (optimalBufferSize >= 0) { 174cb93a386Sopenharmony_ci auto setBufferResult = streamP->setBufferSizeInFrames(optimalBufferSize); 175cb93a386Sopenharmony_ci if (!setBufferResult) { 176cb93a386Sopenharmony_ci LOGW("Failed to setBufferSizeInFrames(%d). Error was %s", 177cb93a386Sopenharmony_ci optimalBufferSize, 178cb93a386Sopenharmony_ci convertToText(setBufferResult.error())); 179cb93a386Sopenharmony_ci } 180cb93a386Sopenharmony_ci } 181cb93a386Sopenharmony_ci 182cb93a386Sopenharmony_ci *streamPP = streamP; 183cb93a386Sopenharmony_ci } else { 184cb93a386Sopenharmony_ci delete streamP; 185cb93a386Sopenharmony_ci } 186cb93a386Sopenharmony_ci return result; 187cb93a386Sopenharmony_ci} 188cb93a386Sopenharmony_ci 189cb93a386Sopenharmony_ciResult AudioStreamBuilder::openManagedStream(oboe::ManagedStream &stream) { 190cb93a386Sopenharmony_ci stream.reset(); 191cb93a386Sopenharmony_ci auto result = isValidConfig(); 192cb93a386Sopenharmony_ci if (result != Result::OK) { 193cb93a386Sopenharmony_ci return result; 194cb93a386Sopenharmony_ci } 195cb93a386Sopenharmony_ci AudioStream *streamptr; 196cb93a386Sopenharmony_ci result = openStream(&streamptr); 197cb93a386Sopenharmony_ci stream.reset(streamptr); 198cb93a386Sopenharmony_ci return result; 199cb93a386Sopenharmony_ci} 200cb93a386Sopenharmony_ci 201cb93a386Sopenharmony_ciResult AudioStreamBuilder::openStream(std::shared_ptr<AudioStream> &sharedStream) { 202cb93a386Sopenharmony_ci sharedStream.reset(); 203cb93a386Sopenharmony_ci auto result = isValidConfig(); 204cb93a386Sopenharmony_ci if (result != Result::OK) { 205cb93a386Sopenharmony_ci return result; 206cb93a386Sopenharmony_ci } 207cb93a386Sopenharmony_ci AudioStream *streamptr; 208cb93a386Sopenharmony_ci result = openStream(&streamptr); 209cb93a386Sopenharmony_ci if (result == Result::OK) { 210cb93a386Sopenharmony_ci sharedStream.reset(streamptr); 211cb93a386Sopenharmony_ci // Save a weak_ptr in the stream for use with callbacks. 212cb93a386Sopenharmony_ci streamptr->setWeakThis(sharedStream); 213cb93a386Sopenharmony_ci } 214cb93a386Sopenharmony_ci return result; 215cb93a386Sopenharmony_ci} 216cb93a386Sopenharmony_ci 217cb93a386Sopenharmony_ci} // namespace oboe 218