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