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_input.h" 6 7 #include "base/debug/trace_event.h" 8 #include "base/logging.h" 9 #include "media/audio/android/audio_manager_android.h" 10 #include "media/base/audio_bus.h" 11 12 #define LOG_ON_FAILURE_AND_RETURN(op, ...) \ 13 do { \ 14 SLresult err = (op); \ 15 if (err != SL_RESULT_SUCCESS) { \ 16 DLOG(ERROR) << #op << " failed: " << err; \ 17 return __VA_ARGS__; \ 18 } \ 19 } while (0) 20 21 namespace media { 22 23 OpenSLESInputStream::OpenSLESInputStream(AudioManagerAndroid* audio_manager, 24 const AudioParameters& params) 25 : audio_manager_(audio_manager), 26 callback_(NULL), 27 recorder_(NULL), 28 simple_buffer_queue_(NULL), 29 active_buffer_index_(0), 30 buffer_size_bytes_(0), 31 started_(false), 32 audio_bus_(media::AudioBus::Create(params)) { 33 DVLOG(2) << __PRETTY_FUNCTION__; 34 format_.formatType = SL_DATAFORMAT_PCM; 35 format_.numChannels = static_cast<SLuint32>(params.channels()); 36 // Provides sampling rate in milliHertz to OpenSLES. 37 format_.samplesPerSec = static_cast<SLuint32>(params.sample_rate() * 1000); 38 format_.bitsPerSample = params.bits_per_sample(); 39 format_.containerSize = params.bits_per_sample(); 40 format_.endianness = SL_BYTEORDER_LITTLEENDIAN; 41 if (format_.numChannels == 1) 42 format_.channelMask = SL_SPEAKER_FRONT_CENTER; 43 else if (format_.numChannels == 2) 44 format_.channelMask = SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT; 45 else 46 NOTREACHED() << "Unsupported number of channels: " << format_.numChannels; 47 48 buffer_size_bytes_ = params.GetBytesPerBuffer(); 49 50 memset(&audio_data_, 0, sizeof(audio_data_)); 51 } 52 53 OpenSLESInputStream::~OpenSLESInputStream() { 54 DVLOG(2) << __PRETTY_FUNCTION__; 55 DCHECK(thread_checker_.CalledOnValidThread()); 56 DCHECK(!recorder_object_.Get()); 57 DCHECK(!engine_object_.Get()); 58 DCHECK(!recorder_); 59 DCHECK(!simple_buffer_queue_); 60 DCHECK(!audio_data_[0]); 61 } 62 63 bool OpenSLESInputStream::Open() { 64 DVLOG(2) << __PRETTY_FUNCTION__; 65 DCHECK(thread_checker_.CalledOnValidThread()); 66 if (engine_object_.Get()) 67 return false; 68 69 if (!CreateRecorder()) 70 return false; 71 72 SetupAudioBuffer(); 73 74 return true; 75 } 76 77 void OpenSLESInputStream::Start(AudioInputCallback* callback) { 78 DVLOG(2) << __PRETTY_FUNCTION__; 79 DCHECK(thread_checker_.CalledOnValidThread()); 80 DCHECK(callback); 81 DCHECK(recorder_); 82 DCHECK(simple_buffer_queue_); 83 if (started_) 84 return; 85 86 base::AutoLock lock(lock_); 87 DCHECK(callback_ == NULL || callback_ == callback); 88 callback_ = callback; 89 active_buffer_index_ = 0; 90 91 // Enqueues kMaxNumOfBuffersInQueue zero buffers to get the ball rolling. 92 // TODO(henrika): add support for Start/Stop/Start sequences when we are 93 // able to clear the buffer queue. There is currently a bug in the OpenSLES 94 // implementation which forces us to always call Stop() and Close() before 95 // calling Start() again. 96 SLresult err = SL_RESULT_UNKNOWN_ERROR; 97 for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) { 98 err = (*simple_buffer_queue_)->Enqueue( 99 simple_buffer_queue_, audio_data_[i], buffer_size_bytes_); 100 if (SL_RESULT_SUCCESS != err) { 101 HandleError(err); 102 started_ = false; 103 return; 104 } 105 } 106 107 // Start the recording by setting the state to SL_RECORDSTATE_RECORDING. 108 // When the object is in the SL_RECORDSTATE_RECORDING state, adding buffers 109 // will implicitly start the filling process. 110 err = (*recorder_)->SetRecordState(recorder_, SL_RECORDSTATE_RECORDING); 111 if (SL_RESULT_SUCCESS != err) { 112 HandleError(err); 113 started_ = false; 114 return; 115 } 116 117 started_ = true; 118 } 119 120 void OpenSLESInputStream::Stop() { 121 DVLOG(2) << __PRETTY_FUNCTION__; 122 DCHECK(thread_checker_.CalledOnValidThread()); 123 if (!started_) 124 return; 125 126 base::AutoLock lock(lock_); 127 128 // Stop recording by setting the record state to SL_RECORDSTATE_STOPPED. 129 LOG_ON_FAILURE_AND_RETURN( 130 (*recorder_)->SetRecordState(recorder_, SL_RECORDSTATE_STOPPED)); 131 132 // Clear the buffer queue to get rid of old data when resuming recording. 133 LOG_ON_FAILURE_AND_RETURN( 134 (*simple_buffer_queue_)->Clear(simple_buffer_queue_)); 135 136 started_ = false; 137 callback_ = NULL; 138 } 139 140 void OpenSLESInputStream::Close() { 141 DVLOG(2) << __PRETTY_FUNCTION__; 142 DCHECK(thread_checker_.CalledOnValidThread()); 143 144 // Stop the stream if it is still recording. 145 Stop(); 146 { 147 // TODO(henrika): Do we need to hold the lock here? 148 base::AutoLock lock(lock_); 149 150 // Destroy the buffer queue recorder object and invalidate all associated 151 // interfaces. 152 recorder_object_.Reset(); 153 simple_buffer_queue_ = NULL; 154 recorder_ = NULL; 155 156 // Destroy the engine object. We don't store any associated interface for 157 // this object. 158 engine_object_.Reset(); 159 ReleaseAudioBuffer(); 160 } 161 162 audio_manager_->ReleaseInputStream(this); 163 } 164 165 double OpenSLESInputStream::GetMaxVolume() { 166 NOTIMPLEMENTED(); 167 return 0.0; 168 } 169 170 void OpenSLESInputStream::SetVolume(double volume) { 171 NOTIMPLEMENTED(); 172 } 173 174 double OpenSLESInputStream::GetVolume() { 175 NOTIMPLEMENTED(); 176 return 0.0; 177 } 178 179 void OpenSLESInputStream::SetAutomaticGainControl(bool enabled) { 180 NOTIMPLEMENTED(); 181 } 182 183 bool OpenSLESInputStream::GetAutomaticGainControl() { 184 NOTIMPLEMENTED(); 185 return false; 186 } 187 188 bool OpenSLESInputStream::CreateRecorder() { 189 DCHECK(thread_checker_.CalledOnValidThread()); 190 DCHECK(!engine_object_.Get()); 191 DCHECK(!recorder_object_.Get()); 192 DCHECK(!recorder_); 193 DCHECK(!simple_buffer_queue_); 194 195 // Initializes the engine object with specific option. After working with the 196 // object, we need to free the object and its resources. 197 SLEngineOption option[] = { 198 {SL_ENGINEOPTION_THREADSAFE, static_cast<SLuint32>(SL_BOOLEAN_TRUE)}}; 199 LOG_ON_FAILURE_AND_RETURN( 200 slCreateEngine(engine_object_.Receive(), 1, option, 0, NULL, NULL), 201 false); 202 203 // Realize the SL engine object in synchronous mode. 204 LOG_ON_FAILURE_AND_RETURN( 205 engine_object_->Realize(engine_object_.Get(), SL_BOOLEAN_FALSE), false); 206 207 // Get the SL engine interface which is implicit. 208 SLEngineItf engine; 209 LOG_ON_FAILURE_AND_RETURN(engine_object_->GetInterface( 210 engine_object_.Get(), SL_IID_ENGINE, &engine), 211 false); 212 213 // Audio source configuration. 214 SLDataLocator_IODevice mic_locator = { 215 SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, 216 SL_DEFAULTDEVICEID_AUDIOINPUT, NULL}; 217 SLDataSource audio_source = {&mic_locator, NULL}; 218 219 // Audio sink configuration. 220 SLDataLocator_AndroidSimpleBufferQueue buffer_queue = { 221 SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 222 static_cast<SLuint32>(kMaxNumOfBuffersInQueue)}; 223 SLDataSink audio_sink = {&buffer_queue, &format_}; 224 225 // Create an audio recorder. 226 const SLInterfaceID interface_id[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE, 227 SL_IID_ANDROIDCONFIGURATION}; 228 const SLboolean interface_required[] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE}; 229 230 // Create AudioRecorder and specify SL_IID_ANDROIDCONFIGURATION. 231 LOG_ON_FAILURE_AND_RETURN( 232 (*engine)->CreateAudioRecorder(engine, 233 recorder_object_.Receive(), 234 &audio_source, 235 &audio_sink, 236 arraysize(interface_id), 237 interface_id, 238 interface_required), 239 false); 240 241 SLAndroidConfigurationItf recorder_config; 242 LOG_ON_FAILURE_AND_RETURN( 243 recorder_object_->GetInterface(recorder_object_.Get(), 244 SL_IID_ANDROIDCONFIGURATION, 245 &recorder_config), 246 false); 247 248 // Uses the main microphone tuned for audio communications. 249 SLint32 stream_type = SL_ANDROID_RECORDING_PRESET_VOICE_COMMUNICATION; 250 LOG_ON_FAILURE_AND_RETURN( 251 (*recorder_config)->SetConfiguration(recorder_config, 252 SL_ANDROID_KEY_RECORDING_PRESET, 253 &stream_type, 254 sizeof(SLint32)), 255 false); 256 257 // Realize the recorder object in synchronous mode. 258 LOG_ON_FAILURE_AND_RETURN( 259 recorder_object_->Realize(recorder_object_.Get(), SL_BOOLEAN_FALSE), 260 false); 261 262 // Get an implicit recorder interface. 263 LOG_ON_FAILURE_AND_RETURN( 264 recorder_object_->GetInterface( 265 recorder_object_.Get(), SL_IID_RECORD, &recorder_), 266 false); 267 268 // Get the simple buffer queue interface. 269 LOG_ON_FAILURE_AND_RETURN( 270 recorder_object_->GetInterface(recorder_object_.Get(), 271 SL_IID_ANDROIDSIMPLEBUFFERQUEUE, 272 &simple_buffer_queue_), 273 false); 274 275 // Register the input callback for the simple buffer queue. 276 // This callback will be called when receiving new data from the device. 277 LOG_ON_FAILURE_AND_RETURN( 278 (*simple_buffer_queue_)->RegisterCallback( 279 simple_buffer_queue_, SimpleBufferQueueCallback, this), 280 false); 281 282 return true; 283 } 284 285 void OpenSLESInputStream::SimpleBufferQueueCallback( 286 SLAndroidSimpleBufferQueueItf buffer_queue, 287 void* instance) { 288 OpenSLESInputStream* stream = 289 reinterpret_cast<OpenSLESInputStream*>(instance); 290 stream->ReadBufferQueue(); 291 } 292 293 void OpenSLESInputStream::ReadBufferQueue() { 294 base::AutoLock lock(lock_); 295 if (!started_) 296 return; 297 298 TRACE_EVENT0("audio", "OpenSLESOutputStream::ReadBufferQueue"); 299 300 // Convert from interleaved format to deinterleaved audio bus format. 301 audio_bus_->FromInterleaved(audio_data_[active_buffer_index_], 302 audio_bus_->frames(), 303 format_.bitsPerSample / 8); 304 305 // TODO(henrika): Investigate if it is possible to get an accurate 306 // delay estimation. 307 callback_->OnData(this, audio_bus_.get(), buffer_size_bytes_, 0.0); 308 309 // Done with this buffer. Send it to device for recording. 310 SLresult err = 311 (*simple_buffer_queue_)->Enqueue(simple_buffer_queue_, 312 audio_data_[active_buffer_index_], 313 buffer_size_bytes_); 314 if (SL_RESULT_SUCCESS != err) 315 HandleError(err); 316 317 active_buffer_index_ = (active_buffer_index_ + 1) % kMaxNumOfBuffersInQueue; 318 } 319 320 void OpenSLESInputStream::SetupAudioBuffer() { 321 DCHECK(thread_checker_.CalledOnValidThread()); 322 DCHECK(!audio_data_[0]); 323 for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) { 324 audio_data_[i] = new uint8[buffer_size_bytes_]; 325 } 326 } 327 328 void OpenSLESInputStream::ReleaseAudioBuffer() { 329 DCHECK(thread_checker_.CalledOnValidThread()); 330 if (audio_data_[0]) { 331 for (int i = 0; i < kMaxNumOfBuffersInQueue; ++i) { 332 delete[] audio_data_[i]; 333 audio_data_[i] = NULL; 334 } 335 } 336 } 337 338 void OpenSLESInputStream::HandleError(SLresult error) { 339 DLOG(ERROR) << "OpenSLES Input error " << error; 340 if (callback_) 341 callback_->OnError(this); 342 } 343 344 } // namespace media 345