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