1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "media/audio/android/opensles_output.h" 6 7 #include "base/debug/trace_event.h" 8 #include "base/logging.h" 9 #include "media/audio/android/audio_manager_android.h" 10 11 #define LOG_ON_FAILURE_AND_RETURN(op, ...) \ 12 do { \ 13 SLresult err = (op); \ 14 if (err != SL_RESULT_SUCCESS) { \ 15 DLOG(ERROR) << #op << " failed: " << err; \ 16 return __VA_ARGS__; \ 17 } \ 18 } while (0) 19 20 namespace media { 21 22 OpenSLESOutputStream::OpenSLESOutputStream(AudioManagerAndroid* manager, 23 const AudioParameters& params) 24 : audio_manager_(manager), 25 callback_(NULL), 26 player_(NULL), 27 simple_buffer_queue_(NULL), 28 active_queue_(0), 29 buffer_size_bytes_(0), 30 started_(false), 31 volume_(1.0) { 32 format_.formatType = SL_DATAFORMAT_PCM; 33 format_.numChannels = static_cast<SLuint32>(params.channels()); 34 // Provides sampling rate in milliHertz to OpenSLES. 35 format_.samplesPerSec = static_cast<SLuint32>(params.sample_rate() * 1000); 36 format_.bitsPerSample = params.bits_per_sample(); 37 format_.containerSize = params.bits_per_sample(); 38 format_.endianness = SL_BYTEORDER_LITTLEENDIAN; 39 if (format_.numChannels == 1) 40 format_.channelMask = SL_SPEAKER_FRONT_CENTER; 41 else if (format_.numChannels == 2) 42 format_.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; 43 else 44 NOTREACHED() << "Unsupported number of channels: " << format_.numChannels; 45 46 buffer_size_bytes_ = params.GetBytesPerBuffer(); 47 audio_bus_ = AudioBus::Create(params); 48 49 memset(&audio_data_, 0, sizeof(audio_data_)); 50 } 51 52 OpenSLESOutputStream::~OpenSLESOutputStream() { 53 DCHECK(!engine_object_.Get()); 54 DCHECK(!player_object_.Get()); 55 DCHECK(!output_mixer_.Get()); 56 DCHECK(!player_); 57 DCHECK(!simple_buffer_queue_); 58 DCHECK(!audio_data_[0]); 59 } 60 61 bool OpenSLESOutputStream::Open() { 62 if (engine_object_.Get()) 63 return false; 64 65 if (!CreatePlayer()) 66 return false; 67 68 SetupAudioBuffer(); 69 70 return true; 71 } 72 73 void OpenSLESOutputStream::Start(AudioSourceCallback* callback) { 74 DCHECK(callback); 75 DCHECK(player_); 76 DCHECK(simple_buffer_queue_); 77 if (started_) 78 return; 79 80 // Enable the flags before streaming. 81 callback_ = callback; 82 active_queue_ = 0; 83 started_ = true; 84 85 // Avoid start-up glitches by filling up one buffer queue before starting 86 // the stream. 87 FillBufferQueue(); 88 89 // Start streaming data by setting the play state to |SL_PLAYSTATE_PLAYING|. 90 LOG_ON_FAILURE_AND_RETURN( 91 (*player_)->SetPlayState(player_, SL_PLAYSTATE_PLAYING)); 92 } 93 94 void OpenSLESOutputStream::Stop() { 95 if (!started_) 96 return; 97 98 started_ = false; 99 // Stop playing by setting the play state to |SL_PLAYSTATE_STOPPED|. 100 LOG_ON_FAILURE_AND_RETURN( 101 (*player_)->SetPlayState(player_, SL_PLAYSTATE_STOPPED)); 102 103 // Clear the buffer queue so that the old data won't be played when 104 // resuming playing. 105 LOG_ON_FAILURE_AND_RETURN( 106 (*simple_buffer_queue_)->Clear(simple_buffer_queue_)); 107 } 108 109 void OpenSLESOutputStream::Close() { 110 // Stop the stream if it is still playing. 111 Stop(); 112 113 // Explicitly free the player objects and invalidate their associated 114 // interfaces. They have to be done in the correct order. 115 player_object_.Reset(); 116 output_mixer_.Reset(); 117 engine_object_.Reset(); 118 simple_buffer_queue_ = NULL; 119 player_ = NULL; 120 121 ReleaseAudioBuffer(); 122 123 audio_manager_->ReleaseOutputStream(this); 124 } 125 126 void OpenSLESOutputStream::SetVolume(double volume) { 127 float volume_float = static_cast<float>(volume); 128 if (volume_float < 0.0f || volume_float > 1.0f) { 129 return; 130 } 131 volume_ = volume_float; 132 } 133 134 void OpenSLESOutputStream::GetVolume(double* volume) { 135 *volume = static_cast<double>(volume_); 136 } 137 138 bool OpenSLESOutputStream::CreatePlayer() { 139 // Initializes the engine object with specific option. After working with the 140 // object, we need to free the object and its resources. 141 SLEngineOption option[] = { 142 { SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE) } 143 }; 144 LOG_ON_FAILURE_AND_RETURN( 145 slCreateEngine(engine_object_.Receive(), 1, option, 0, NULL, NULL), 146 false); 147 148 // Realize the SL engine object in synchronous mode. 149 LOG_ON_FAILURE_AND_RETURN( 150 engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE), 151 false); 152 153 // Get the SL engine interface which is implicit. 154 SLEngineItf engine; 155 LOG_ON_FAILURE_AND_RETURN( 156 engine_object_->GetInterface(engine_object_.Get(), 157 SL_IID_ENGINE, 158 &engine), 159 false); 160 161 // Create ouput mixer object to be used by the player. 162 LOG_ON_FAILURE_AND_RETURN( 163 (*engine)->CreateOutputMix(engine, 164 output_mixer_.Receive(), 165 0, 166 NULL, 167 NULL), 168 false); 169 170 // Realizing the output mix object in synchronous mode. 171 LOG_ON_FAILURE_AND_RETURN( 172 output_mixer_->Realize(output_mixer_.Get(), SL_BOOLEAN_FALSE), 173 false); 174 175 // Audio source configuration. 176 SLDataLocator_AndroidSimpleBufferQueue simple_buffer_queue = { 177 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 178 static_cast<SLuint32>(kNumOfQueuesInBuffer) 179 }; 180 SLDataSource audio_source = { &simple_buffer_queue, &format_ }; 181 182 // Audio sink configuration. 183 SLDataLocator_OutputMix locator_output_mix = { 184 SL_DATALOCATOR_OUTPUTMIX, output_mixer_.Get() 185 }; 186 SLDataSink audio_sink = { &locator_output_mix, NULL }; 187 188 // Create an audio player. 189 const SLInterfaceID interface_id[] = { 190 SL_IID_BUFFERQUEUE, 191 SL_IID_VOLUME, 192 SL_IID_ANDROIDCONFIGURATION 193 }; 194 const SLboolean interface_required[] = { 195 SL_BOOLEAN_TRUE, 196 SL_BOOLEAN_TRUE, 197 SL_BOOLEAN_TRUE 198 }; 199 LOG_ON_FAILURE_AND_RETURN( 200 (*engine)->CreateAudioPlayer(engine, 201 player_object_.Receive(), 202 &audio_source, 203 &audio_sink, 204 arraysize(interface_id), 205 interface_id, 206 interface_required), 207 false); 208 209 // Create AudioPlayer and specify SL_IID_ANDROIDCONFIGURATION. 210 SLAndroidConfigurationItf player_config; 211 LOG_ON_FAILURE_AND_RETURN( 212 player_object_->GetInterface(player_object_.Get(), 213 SL_IID_ANDROIDCONFIGURATION, 214 &player_config), 215 false); 216 217 SLint32 stream_type = SL_ANDROID_STREAM_VOICE; 218 LOG_ON_FAILURE_AND_RETURN( 219 (*player_config)->SetConfiguration(player_config, 220 SL_ANDROID_KEY_STREAM_TYPE, 221 &stream_type, sizeof(SLint32)), 222 false); 223 224 // Realize the player object in synchronous mode. 225 LOG_ON_FAILURE_AND_RETURN( 226 player_object_->Realize(player_object_.Get(), SL_BOOLEAN_FALSE), 227 false); 228 229 // Get an implicit player interface. 230 LOG_ON_FAILURE_AND_RETURN( 231 player_object_->GetInterface(player_object_.Get(), SL_IID_PLAY, &player_), 232 false); 233 234 // Get the simple buffer queue interface. 235 LOG_ON_FAILURE_AND_RETURN( 236 player_object_->GetInterface(player_object_.Get(), 237 SL_IID_BUFFERQUEUE, 238 &simple_buffer_queue_), 239 false); 240 241 // Register the input callback for the simple buffer queue. 242 // This callback will be called when the soundcard needs data. 243 LOG_ON_FAILURE_AND_RETURN( 244 (*simple_buffer_queue_)->RegisterCallback(simple_buffer_queue_, 245 SimpleBufferQueueCallback, 246 this), 247 false); 248 249 return true; 250 } 251 252 void OpenSLESOutputStream::SimpleBufferQueueCallback( 253 SLAndroidSimpleBufferQueueItf buffer_queue, void* instance) { 254 OpenSLESOutputStream* stream = 255 reinterpret_cast<OpenSLESOutputStream*>(instance); 256 stream->FillBufferQueue(); 257 } 258 259 void OpenSLESOutputStream::FillBufferQueue() { 260 if (!started_) 261 return; 262 263 TRACE_EVENT0("audio", "OpenSLESOutputStream::FillBufferQueue"); 264 // Read data from the registered client source. 265 // TODO(xians): Get an accurate delay estimation. 266 uint32 hardware_delay = buffer_size_bytes_; 267 int frames_filled = callback_->OnMoreData( 268 audio_bus_.get(), AudioBuffersState(0, hardware_delay)); 269 if (frames_filled <= 0) 270 return; // Audio source is shutting down, or halted on error. 271 int num_filled_bytes = 272 frames_filled * audio_bus_->channels() * format_.bitsPerSample / 8; 273 DCHECK_LE(static_cast<size_t>(num_filled_bytes), buffer_size_bytes_); 274 // Note: If this ever changes to output raw float the data must be clipped and 275 // sanitized since it may come from an untrusted source such as NaCl. 276 audio_bus_->Scale(volume_); 277 audio_bus_->ToInterleaved( 278 frames_filled, format_.bitsPerSample / 8, audio_data_[active_queue_]); 279 280 // Enqueue the buffer for playback. 281 SLresult err = (*simple_buffer_queue_)->Enqueue( 282 simple_buffer_queue_, 283 audio_data_[active_queue_], 284 num_filled_bytes); 285 if (SL_RESULT_SUCCESS != err) 286 HandleError(err); 287 288 active_queue_ = (active_queue_ + 1) % kNumOfQueuesInBuffer; 289 } 290 291 void OpenSLESOutputStream::SetupAudioBuffer() { 292 DCHECK(!audio_data_[0]); 293 for (int i = 0; i < kNumOfQueuesInBuffer; ++i) { 294 audio_data_[i] = new uint8[buffer_size_bytes_]; 295 } 296 } 297 298 void OpenSLESOutputStream::ReleaseAudioBuffer() { 299 if (audio_data_[0]) { 300 for (int i = 0; i < kNumOfQueuesInBuffer; ++i) { 301 delete [] audio_data_[i]; 302 audio_data_[i] = NULL; 303 } 304 } 305 } 306 307 void OpenSLESOutputStream::HandleError(SLresult error) { 308 DLOG(ERROR) << "OpenSLES Output error " << error; 309 if (callback_) 310 callback_->OnError(this); 311 } 312 313 } // namespace media 314