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/audio_input_controller.h" 6 7 #include "base/bind.h" 8 #include "base/threading/thread_restrictions.h" 9 #include "media/base/limits.h" 10 #include "media/base/scoped_histogram_timer.h" 11 #include "media/base/user_input_monitor.h" 12 13 namespace { 14 const int kMaxInputChannels = 2; 15 16 // TODO(henrika): remove usage of timers and add support for proper 17 // notification of when the input device is removed. This was originally added 18 // to resolve http://crbug.com/79936 for Windows platforms. This then caused 19 // breakage (very hard to repro bugs!) on other platforms: See 20 // http://crbug.com/226327 and http://crbug.com/230972. 21 const int kTimerResetIntervalSeconds = 1; 22 // We have received reports that the timer can be too trigger happy on some 23 // Mac devices and the initial timer interval has therefore been increased 24 // from 1 second to 5 seconds. 25 const int kTimerInitialIntervalSeconds = 5; 26 } 27 28 namespace media { 29 30 // static 31 AudioInputController::Factory* AudioInputController::factory_ = NULL; 32 33 AudioInputController::AudioInputController(EventHandler* handler, 34 SyncWriter* sync_writer, 35 UserInputMonitor* user_input_monitor) 36 : creator_loop_(base::MessageLoopProxy::current()), 37 handler_(handler), 38 stream_(NULL), 39 data_is_active_(false), 40 state_(kEmpty), 41 sync_writer_(sync_writer), 42 max_volume_(0.0), 43 user_input_monitor_(user_input_monitor), 44 prev_key_down_count_(0) { 45 DCHECK(creator_loop_.get()); 46 } 47 48 AudioInputController::~AudioInputController() { 49 DCHECK(kClosed == state_ || kCreated == state_ || kEmpty == state_); 50 } 51 52 // static 53 scoped_refptr<AudioInputController> AudioInputController::Create( 54 AudioManager* audio_manager, 55 EventHandler* event_handler, 56 const AudioParameters& params, 57 const std::string& device_id, 58 UserInputMonitor* user_input_monitor) { 59 DCHECK(audio_manager); 60 61 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) 62 return NULL; 63 64 if (factory_) { 65 return factory_->Create( 66 audio_manager, event_handler, params, user_input_monitor); 67 } 68 scoped_refptr<AudioInputController> controller( 69 new AudioInputController(event_handler, NULL, user_input_monitor)); 70 71 controller->message_loop_ = audio_manager->GetMessageLoop(); 72 73 // Create and open a new audio input stream from the existing 74 // audio-device thread. 75 if (!controller->message_loop_->PostTask(FROM_HERE, 76 base::Bind(&AudioInputController::DoCreate, controller, 77 base::Unretained(audio_manager), params, device_id))) { 78 controller = NULL; 79 } 80 81 return controller; 82 } 83 84 // static 85 scoped_refptr<AudioInputController> AudioInputController::CreateLowLatency( 86 AudioManager* audio_manager, 87 EventHandler* event_handler, 88 const AudioParameters& params, 89 const std::string& device_id, 90 SyncWriter* sync_writer, 91 UserInputMonitor* user_input_monitor) { 92 DCHECK(audio_manager); 93 DCHECK(sync_writer); 94 95 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) 96 return NULL; 97 98 // Create the AudioInputController object and ensure that it runs on 99 // the audio-manager thread. 100 scoped_refptr<AudioInputController> controller( 101 new AudioInputController(event_handler, sync_writer, user_input_monitor)); 102 controller->message_loop_ = audio_manager->GetMessageLoop(); 103 104 // Create and open a new audio input stream from the existing 105 // audio-device thread. Use the provided audio-input device. 106 if (!controller->message_loop_->PostTask(FROM_HERE, 107 base::Bind(&AudioInputController::DoCreate, controller, 108 base::Unretained(audio_manager), params, device_id))) { 109 controller = NULL; 110 } 111 112 return controller; 113 } 114 115 // static 116 scoped_refptr<AudioInputController> AudioInputController::CreateForStream( 117 const scoped_refptr<base::MessageLoopProxy>& message_loop, 118 EventHandler* event_handler, 119 AudioInputStream* stream, 120 SyncWriter* sync_writer, 121 UserInputMonitor* user_input_monitor) { 122 DCHECK(sync_writer); 123 DCHECK(stream); 124 125 // Create the AudioInputController object and ensure that it runs on 126 // the audio-manager thread. 127 scoped_refptr<AudioInputController> controller( 128 new AudioInputController(event_handler, sync_writer, user_input_monitor)); 129 controller->message_loop_ = message_loop; 130 131 // TODO(miu): See TODO at top of file. Until that's resolved, we need to 132 // disable the error auto-detection here (since the audio mirroring 133 // implementation will reliably report error and close events). Note, of 134 // course, that we're assuming CreateForStream() has been called for the audio 135 // mirroring use case only. 136 if (!controller->message_loop_->PostTask( 137 FROM_HERE, 138 base::Bind(&AudioInputController::DoCreateForStream, controller, 139 stream, false))) { 140 controller = NULL; 141 } 142 143 return controller; 144 } 145 146 void AudioInputController::Record() { 147 message_loop_->PostTask(FROM_HERE, base::Bind( 148 &AudioInputController::DoRecord, this)); 149 } 150 151 void AudioInputController::Close(const base::Closure& closed_task) { 152 DCHECK(!closed_task.is_null()); 153 DCHECK(creator_loop_->BelongsToCurrentThread()); 154 155 message_loop_->PostTaskAndReply( 156 FROM_HERE, base::Bind(&AudioInputController::DoClose, this), closed_task); 157 } 158 159 void AudioInputController::SetVolume(double volume) { 160 message_loop_->PostTask(FROM_HERE, base::Bind( 161 &AudioInputController::DoSetVolume, this, volume)); 162 } 163 164 void AudioInputController::SetAutomaticGainControl(bool enabled) { 165 message_loop_->PostTask(FROM_HERE, base::Bind( 166 &AudioInputController::DoSetAutomaticGainControl, this, enabled)); 167 } 168 169 void AudioInputController::DoCreate(AudioManager* audio_manager, 170 const AudioParameters& params, 171 const std::string& device_id) { 172 DCHECK(message_loop_->BelongsToCurrentThread()); 173 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CreateTime"); 174 // TODO(miu): See TODO at top of file. Until that's resolved, assume all 175 // platform audio input requires the |no_data_timer_| be used to auto-detect 176 // errors. In reality, probably only Windows needs to be treated as 177 // unreliable here. 178 DoCreateForStream(audio_manager->MakeAudioInputStream(params, device_id), 179 true); 180 } 181 182 void AudioInputController::DoCreateForStream( 183 AudioInputStream* stream_to_control, bool enable_nodata_timer) { 184 DCHECK(message_loop_->BelongsToCurrentThread()); 185 186 DCHECK(!stream_); 187 stream_ = stream_to_control; 188 189 if (!stream_) { 190 handler_->OnError(this); 191 return; 192 } 193 194 if (stream_ && !stream_->Open()) { 195 stream_->Close(); 196 stream_ = NULL; 197 handler_->OnError(this); 198 return; 199 } 200 201 DCHECK(!no_data_timer_.get()); 202 if (enable_nodata_timer) { 203 // Create the data timer which will call DoCheckForNoData(). The timer 204 // is started in DoRecord() and restarted in each DoCheckForNoData() 205 // callback. 206 no_data_timer_.reset(new base::Timer( 207 FROM_HERE, base::TimeDelta::FromSeconds(kTimerInitialIntervalSeconds), 208 base::Bind(&AudioInputController::DoCheckForNoData, 209 base::Unretained(this)), false)); 210 } else { 211 DVLOG(1) << "Disabled: timer check for no data."; 212 } 213 214 state_ = kCreated; 215 handler_->OnCreated(this); 216 217 if (user_input_monitor_) { 218 user_input_monitor_->EnableKeyPressMonitoring(); 219 prev_key_down_count_ = user_input_monitor_->GetKeyPressCount(); 220 } 221 } 222 223 void AudioInputController::DoRecord() { 224 DCHECK(message_loop_->BelongsToCurrentThread()); 225 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.RecordTime"); 226 227 if (state_ != kCreated) 228 return; 229 230 { 231 base::AutoLock auto_lock(lock_); 232 state_ = kRecording; 233 } 234 235 if (no_data_timer_) { 236 // Start the data timer. Once |kTimerResetIntervalSeconds| have passed, 237 // a callback to DoCheckForNoData() is made. 238 no_data_timer_->Reset(); 239 } 240 241 stream_->Start(this); 242 handler_->OnRecording(this); 243 } 244 245 void AudioInputController::DoClose() { 246 DCHECK(message_loop_->BelongsToCurrentThread()); 247 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CloseTime"); 248 249 // Delete the timer on the same thread that created it. 250 no_data_timer_.reset(); 251 252 if (state_ != kClosed) { 253 DoStopCloseAndClearStream(NULL); 254 SetDataIsActive(false); 255 256 if (LowLatencyMode()) { 257 sync_writer_->Close(); 258 } 259 260 state_ = kClosed; 261 262 if (user_input_monitor_) 263 user_input_monitor_->DisableKeyPressMonitoring(); 264 } 265 } 266 267 void AudioInputController::DoReportError() { 268 DCHECK(message_loop_->BelongsToCurrentThread()); 269 handler_->OnError(this); 270 } 271 272 void AudioInputController::DoSetVolume(double volume) { 273 DCHECK(message_loop_->BelongsToCurrentThread()); 274 DCHECK_GE(volume, 0); 275 DCHECK_LE(volume, 1.0); 276 277 if (state_ != kCreated && state_ != kRecording) 278 return; 279 280 // Only ask for the maximum volume at first call and use cached value 281 // for remaining function calls. 282 if (!max_volume_) { 283 max_volume_ = stream_->GetMaxVolume(); 284 } 285 286 if (max_volume_ == 0.0) { 287 DLOG(WARNING) << "Failed to access input volume control"; 288 return; 289 } 290 291 // Set the stream volume and scale to a range matched to the platform. 292 stream_->SetVolume(max_volume_ * volume); 293 } 294 295 void AudioInputController::DoSetAutomaticGainControl(bool enabled) { 296 DCHECK(message_loop_->BelongsToCurrentThread()); 297 DCHECK_NE(state_, kRecording); 298 299 // Ensure that the AGC state only can be modified before streaming starts. 300 if (state_ != kCreated || state_ == kRecording) 301 return; 302 303 stream_->SetAutomaticGainControl(enabled); 304 } 305 306 void AudioInputController::DoCheckForNoData() { 307 DCHECK(message_loop_->BelongsToCurrentThread()); 308 309 if (!GetDataIsActive()) { 310 // The data-is-active marker will be false only if it has been more than 311 // one second since a data packet was recorded. This can happen if a 312 // capture device has been removed or disabled. 313 handler_->OnError(this); 314 return; 315 } 316 317 // Mark data as non-active. The flag will be re-enabled in OnData() each 318 // time a data packet is received. Hence, under normal conditions, the 319 // flag will only be disabled during a very short period. 320 SetDataIsActive(false); 321 322 // Restart the timer to ensure that we check the flag again in 323 // |kTimerResetIntervalSeconds|. 324 no_data_timer_->Start( 325 FROM_HERE, base::TimeDelta::FromSeconds(kTimerResetIntervalSeconds), 326 base::Bind(&AudioInputController::DoCheckForNoData, 327 base::Unretained(this))); 328 } 329 330 void AudioInputController::OnData(AudioInputStream* stream, 331 const uint8* data, 332 uint32 size, 333 uint32 hardware_delay_bytes, 334 double volume) { 335 { 336 base::AutoLock auto_lock(lock_); 337 if (state_ != kRecording) 338 return; 339 } 340 341 bool key_pressed = false; 342 if (user_input_monitor_) { 343 size_t current_count = user_input_monitor_->GetKeyPressCount(); 344 key_pressed = current_count != prev_key_down_count_; 345 prev_key_down_count_ = current_count; 346 DVLOG_IF(6, key_pressed) << "Detected keypress."; 347 } 348 349 // Mark data as active to ensure that the periodic calls to 350 // DoCheckForNoData() does not report an error to the event handler. 351 SetDataIsActive(true); 352 353 // Use SyncSocket if we are in a low-latency mode. 354 if (LowLatencyMode()) { 355 sync_writer_->Write(data, size, volume, key_pressed); 356 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); 357 return; 358 } 359 360 handler_->OnData(this, data, size); 361 } 362 363 void AudioInputController::OnClose(AudioInputStream* stream) { 364 DVLOG(1) << "AudioInputController::OnClose()"; 365 // TODO(satish): Sometimes the device driver closes the input stream without 366 // us asking for it (may be if the device was unplugged?). Check how to handle 367 // such cases here. 368 } 369 370 void AudioInputController::OnError(AudioInputStream* stream) { 371 // Handle error on the audio-manager thread. 372 message_loop_->PostTask(FROM_HERE, base::Bind( 373 &AudioInputController::DoReportError, this)); 374 } 375 376 void AudioInputController::DoStopCloseAndClearStream( 377 base::WaitableEvent* done) { 378 DCHECK(message_loop_->BelongsToCurrentThread()); 379 380 // Allow calling unconditionally and bail if we don't have a stream to close. 381 if (stream_ != NULL) { 382 stream_->Stop(); 383 stream_->Close(); 384 stream_ = NULL; 385 } 386 387 // Should be last in the method, do not touch "this" from here on. 388 if (done != NULL) 389 done->Signal(); 390 } 391 392 void AudioInputController::SetDataIsActive(bool enabled) { 393 base::subtle::Release_Store(&data_is_active_, enabled); 394 } 395 396 bool AudioInputController::GetDataIsActive() { 397 return (base::subtle::Acquire_Load(&data_is_active_) != false); 398 } 399 400 } // namespace media 401