audio_input_controller.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
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/strings/stringprintf.h" 9#include "base/threading/thread_restrictions.h" 10#include "base/time/time.h" 11#include "media/audio/audio_parameters.h" 12#include "media/base/limits.h" 13#include "media/base/scoped_histogram_timer.h" 14#include "media/base/user_input_monitor.h" 15 16using base::TimeDelta; 17 18namespace { 19const int kMaxInputChannels = 3; 20 21// TODO(henrika): remove usage of timers and add support for proper 22// notification of when the input device is removed. This was originally added 23// to resolve http://crbug.com/79936 for Windows platforms. This then caused 24// breakage (very hard to repro bugs!) on other platforms: See 25// http://crbug.com/226327 and http://crbug.com/230972. 26// See also that the timer has been disabled on Mac now due to 27// crbug.com/357501. 28const int kTimerResetIntervalSeconds = 1; 29// We have received reports that the timer can be too trigger happy on some 30// Mac devices and the initial timer interval has therefore been increased 31// from 1 second to 5 seconds. 32const int kTimerInitialIntervalSeconds = 5; 33 34#if defined(AUDIO_POWER_MONITORING) 35// Time constant for AudioPowerMonitor. 36// The utilized smoothing factor (alpha) in the exponential filter is given 37// by 1-exp(-1/(fs*ts)), where fs is the sample rate in Hz and ts is the time 38// constant given by |kPowerMeasurementTimeConstantMilliseconds|. 39// Example: fs=44100, ts=10e-3 => alpha~0.022420 40// fs=44100, ts=20e-3 => alpha~0.165903 41// A large smoothing factor corresponds to a faster filter response to input 42// changes since y(n)=alpha*x(n)+(1-alpha)*y(n-1), where x(n) is the input 43// and y(n) is the output. 44const int kPowerMeasurementTimeConstantMilliseconds = 10; 45 46// Time in seconds between two successive measurements of audio power levels. 47const int kPowerMonitorLogIntervalSeconds = 5; 48#endif 49} 50 51// Used to log the result of capture startup. 52// This was previously logged as a boolean with only the no callback and OK 53// options. The enum order is kept to ensure backwards compatibility. 54// Elements in this enum should not be deleted or rearranged; the only 55// permitted operation is to add new elements before CAPTURE_STARTUP_RESULT_MAX 56// and update CAPTURE_STARTUP_RESULT_MAX. 57enum CaptureStartupResult { 58 CAPTURE_STARTUP_NO_DATA_CALLBACK = 0, 59 CAPTURE_STARTUP_OK = 1, 60 CAPTURE_STARTUP_CREATE_STREAM_FAILED = 2, 61 CAPTURE_STARTUP_OPEN_STREAM_FAILED = 3, 62 CAPTURE_STARTUP_RESULT_MAX = CAPTURE_STARTUP_OPEN_STREAM_FAILED 63}; 64 65void LogCaptureStartupResult(CaptureStartupResult result) { 66 UMA_HISTOGRAM_ENUMERATION("Media.AudioInputControllerCaptureStartupSuccess", 67 result, 68 CAPTURE_STARTUP_RESULT_MAX + 1); 69 70} 71 72namespace media { 73 74// static 75AudioInputController::Factory* AudioInputController::factory_ = NULL; 76 77AudioInputController::AudioInputController(EventHandler* handler, 78 SyncWriter* sync_writer, 79 UserInputMonitor* user_input_monitor) 80 : creator_task_runner_(base::MessageLoopProxy::current()), 81 handler_(handler), 82 stream_(NULL), 83 data_is_active_(false), 84 state_(CLOSED), 85 sync_writer_(sync_writer), 86 max_volume_(0.0), 87 user_input_monitor_(user_input_monitor), 88#if defined(AUDIO_POWER_MONITORING) 89 log_silence_state_(false), 90 silence_state_(SILENCE_STATE_NO_MEASUREMENT), 91#endif 92 prev_key_down_count_(0) { 93 DCHECK(creator_task_runner_.get()); 94} 95 96AudioInputController::~AudioInputController() { 97 DCHECK_EQ(state_, CLOSED); 98} 99 100// static 101scoped_refptr<AudioInputController> AudioInputController::Create( 102 AudioManager* audio_manager, 103 EventHandler* event_handler, 104 const AudioParameters& params, 105 const std::string& device_id, 106 UserInputMonitor* user_input_monitor) { 107 DCHECK(audio_manager); 108 109 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) 110 return NULL; 111 112 if (factory_) { 113 return factory_->Create( 114 audio_manager, event_handler, params, user_input_monitor); 115 } 116 scoped_refptr<AudioInputController> controller( 117 new AudioInputController(event_handler, NULL, user_input_monitor)); 118 119 controller->task_runner_ = audio_manager->GetTaskRunner(); 120 121 // Create and open a new audio input stream from the existing 122 // audio-device thread. 123 if (!controller->task_runner_->PostTask(FROM_HERE, 124 base::Bind(&AudioInputController::DoCreate, controller, 125 base::Unretained(audio_manager), params, device_id))) { 126 controller = NULL; 127 } 128 129 return controller; 130} 131 132// static 133scoped_refptr<AudioInputController> AudioInputController::CreateLowLatency( 134 AudioManager* audio_manager, 135 EventHandler* event_handler, 136 const AudioParameters& params, 137 const std::string& device_id, 138 SyncWriter* sync_writer, 139 UserInputMonitor* user_input_monitor) { 140 DCHECK(audio_manager); 141 DCHECK(sync_writer); 142 143 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) 144 return NULL; 145 146 // Create the AudioInputController object and ensure that it runs on 147 // the audio-manager thread. 148 scoped_refptr<AudioInputController> controller( 149 new AudioInputController(event_handler, sync_writer, user_input_monitor)); 150 controller->task_runner_ = audio_manager->GetTaskRunner(); 151 152 // Create and open a new audio input stream from the existing 153 // audio-device thread. Use the provided audio-input device. 154 if (!controller->task_runner_->PostTask(FROM_HERE, 155 base::Bind(&AudioInputController::DoCreateForLowLatency, controller, 156 base::Unretained(audio_manager), params, device_id))) { 157 controller = NULL; 158 } 159 160 return controller; 161} 162 163// static 164scoped_refptr<AudioInputController> AudioInputController::CreateForStream( 165 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 166 EventHandler* event_handler, 167 AudioInputStream* stream, 168 SyncWriter* sync_writer, 169 UserInputMonitor* user_input_monitor) { 170 DCHECK(sync_writer); 171 DCHECK(stream); 172 173 // Create the AudioInputController object and ensure that it runs on 174 // the audio-manager thread. 175 scoped_refptr<AudioInputController> controller( 176 new AudioInputController(event_handler, sync_writer, user_input_monitor)); 177 controller->task_runner_ = task_runner; 178 179 // TODO(miu): See TODO at top of file. Until that's resolved, we need to 180 // disable the error auto-detection here (since the audio mirroring 181 // implementation will reliably report error and close events). Note, of 182 // course, that we're assuming CreateForStream() has been called for the audio 183 // mirroring use case only. 184 if (!controller->task_runner_->PostTask( 185 FROM_HERE, 186 base::Bind(&AudioInputController::DoCreateForStream, 187 controller, 188 stream))) { 189 controller = NULL; 190 } 191 192 return controller; 193} 194 195void AudioInputController::Record() { 196 task_runner_->PostTask(FROM_HERE, base::Bind( 197 &AudioInputController::DoRecord, this)); 198} 199 200void AudioInputController::Close(const base::Closure& closed_task) { 201 DCHECK(!closed_task.is_null()); 202 DCHECK(creator_task_runner_->BelongsToCurrentThread()); 203 204 task_runner_->PostTaskAndReply( 205 FROM_HERE, base::Bind(&AudioInputController::DoClose, this), closed_task); 206} 207 208void AudioInputController::SetVolume(double volume) { 209 task_runner_->PostTask(FROM_HERE, base::Bind( 210 &AudioInputController::DoSetVolume, this, volume)); 211} 212 213void AudioInputController::SetAutomaticGainControl(bool enabled) { 214 task_runner_->PostTask(FROM_HERE, base::Bind( 215 &AudioInputController::DoSetAutomaticGainControl, this, enabled)); 216} 217 218void AudioInputController::DoCreate(AudioManager* audio_manager, 219 const AudioParameters& params, 220 const std::string& device_id) { 221 DCHECK(task_runner_->BelongsToCurrentThread()); 222 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CreateTime"); 223 224#if defined(AUDIO_POWER_MONITORING) 225 // Create the audio (power) level meter given the provided audio parameters. 226 // An AudioBus is also needed to wrap the raw data buffer from the native 227 // layer to match AudioPowerMonitor::Scan(). 228 // TODO(henrika): Remove use of extra AudioBus. See http://crbug.com/375155. 229 audio_level_.reset(new media::AudioPowerMonitor( 230 params.sample_rate(), 231 TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMilliseconds))); 232 audio_params_ = params; 233 silence_state_ = SILENCE_STATE_NO_MEASUREMENT; 234#endif 235 236 // TODO(miu): See TODO at top of file. Until that's resolved, assume all 237 // platform audio input requires the |no_data_timer_| be used to auto-detect 238 // errors. In reality, probably only Windows needs to be treated as 239 // unreliable here. 240 DoCreateForStream(audio_manager->MakeAudioInputStream(params, device_id)); 241} 242 243void AudioInputController::DoCreateForLowLatency(AudioManager* audio_manager, 244 const AudioParameters& params, 245 const std::string& device_id) { 246 DCHECK(task_runner_->BelongsToCurrentThread()); 247 248#if defined(AUDIO_POWER_MONITORING) 249 // We only log silence state UMA stats for low latency mode and if we use a 250 // real device. 251 if (params.format() != AudioParameters::AUDIO_FAKE) 252 log_silence_state_ = true; 253#endif 254 255 DoCreate(audio_manager, params, device_id); 256} 257 258void AudioInputController::DoCreateForStream( 259 AudioInputStream* stream_to_control) { 260 DCHECK(task_runner_->BelongsToCurrentThread()); 261 262 DCHECK(!stream_); 263 stream_ = stream_to_control; 264 265 if (!stream_) { 266 if (handler_) 267 handler_->OnError(this, STREAM_CREATE_ERROR); 268 LogCaptureStartupResult(CAPTURE_STARTUP_CREATE_STREAM_FAILED); 269 return; 270 } 271 272 if (stream_ && !stream_->Open()) { 273 stream_->Close(); 274 stream_ = NULL; 275 if (handler_) 276 handler_->OnError(this, STREAM_OPEN_ERROR); 277 LogCaptureStartupResult(CAPTURE_STARTUP_OPEN_STREAM_FAILED); 278 return; 279 } 280 281 DCHECK(!no_data_timer_.get()); 282 283 // Create the data timer which will call FirstCheckForNoData(). The timer 284 // is started in DoRecord() and restarted in each DoCheckForNoData() 285 // callback. 286 // The timer is enabled for logging purposes. The NO_DATA_ERROR triggered 287 // from the timer must be ignored by the EventHandler. 288 // TODO(henrika): remove usage of timer when it has been verified on Canary 289 // that we are safe doing so. Goal is to get rid of |no_data_timer_| and 290 // everything that is tied to it. crbug.com/357569. 291 no_data_timer_.reset(new base::Timer( 292 FROM_HERE, base::TimeDelta::FromSeconds(kTimerInitialIntervalSeconds), 293 base::Bind(&AudioInputController::FirstCheckForNoData, 294 base::Unretained(this)), false)); 295 296 state_ = CREATED; 297 if (handler_) 298 handler_->OnCreated(this); 299 300 if (user_input_monitor_) { 301 user_input_monitor_->EnableKeyPressMonitoring(); 302 prev_key_down_count_ = user_input_monitor_->GetKeyPressCount(); 303 } 304} 305 306void AudioInputController::DoRecord() { 307 DCHECK(task_runner_->BelongsToCurrentThread()); 308 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.RecordTime"); 309 310 if (state_ != CREATED) 311 return; 312 313 { 314 base::AutoLock auto_lock(lock_); 315 state_ = RECORDING; 316 } 317 318 if (no_data_timer_) { 319 // Start the data timer. Once |kTimerResetIntervalSeconds| have passed, 320 // a callback to FirstCheckForNoData() is made. 321 no_data_timer_->Reset(); 322 } 323 324 stream_->Start(this); 325 if (handler_) 326 handler_->OnRecording(this); 327} 328 329void AudioInputController::DoClose() { 330 DCHECK(task_runner_->BelongsToCurrentThread()); 331 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CloseTime"); 332 333 if (state_ == CLOSED) 334 return; 335 336 // Delete the timer on the same thread that created it. 337 no_data_timer_.reset(); 338 339 DoStopCloseAndClearStream(); 340 SetDataIsActive(false); 341 342 if (SharedMemoryAndSyncSocketMode()) 343 sync_writer_->Close(); 344 345 if (user_input_monitor_) 346 user_input_monitor_->DisableKeyPressMonitoring(); 347 348#if defined(AUDIO_POWER_MONITORING) 349 // Send UMA stats if enabled. 350 if (log_silence_state_) 351 LogSilenceState(silence_state_); 352 log_silence_state_ = false; 353#endif 354 355 state_ = CLOSED; 356} 357 358void AudioInputController::DoReportError() { 359 DCHECK(task_runner_->BelongsToCurrentThread()); 360 if (handler_) 361 handler_->OnError(this, STREAM_ERROR); 362} 363 364void AudioInputController::DoSetVolume(double volume) { 365 DCHECK(task_runner_->BelongsToCurrentThread()); 366 DCHECK_GE(volume, 0); 367 DCHECK_LE(volume, 1.0); 368 369 if (state_ != CREATED && state_ != RECORDING) 370 return; 371 372 // Only ask for the maximum volume at first call and use cached value 373 // for remaining function calls. 374 if (!max_volume_) { 375 max_volume_ = stream_->GetMaxVolume(); 376 } 377 378 if (max_volume_ == 0.0) { 379 DLOG(WARNING) << "Failed to access input volume control"; 380 return; 381 } 382 383 // Set the stream volume and scale to a range matched to the platform. 384 stream_->SetVolume(max_volume_ * volume); 385} 386 387void AudioInputController::DoSetAutomaticGainControl(bool enabled) { 388 DCHECK(task_runner_->BelongsToCurrentThread()); 389 DCHECK_NE(state_, RECORDING); 390 391 // Ensure that the AGC state only can be modified before streaming starts. 392 if (state_ != CREATED) 393 return; 394 395 stream_->SetAutomaticGainControl(enabled); 396} 397 398void AudioInputController::FirstCheckForNoData() { 399 DCHECK(task_runner_->BelongsToCurrentThread()); 400 LogCaptureStartupResult(GetDataIsActive() ? 401 CAPTURE_STARTUP_OK : 402 CAPTURE_STARTUP_NO_DATA_CALLBACK); 403 DoCheckForNoData(); 404} 405 406void AudioInputController::DoCheckForNoData() { 407 DCHECK(task_runner_->BelongsToCurrentThread()); 408 409 if (!GetDataIsActive()) { 410 // The data-is-active marker will be false only if it has been more than 411 // one second since a data packet was recorded. This can happen if a 412 // capture device has been removed or disabled. 413 if (handler_) 414 handler_->OnError(this, NO_DATA_ERROR); 415 } 416 417 // Mark data as non-active. The flag will be re-enabled in OnData() each 418 // time a data packet is received. Hence, under normal conditions, the 419 // flag will only be disabled during a very short period. 420 SetDataIsActive(false); 421 422 // Restart the timer to ensure that we check the flag again in 423 // |kTimerResetIntervalSeconds|. 424 no_data_timer_->Start( 425 FROM_HERE, base::TimeDelta::FromSeconds(kTimerResetIntervalSeconds), 426 base::Bind(&AudioInputController::DoCheckForNoData, 427 base::Unretained(this))); 428} 429 430void AudioInputController::OnData(AudioInputStream* stream, 431 const AudioBus* source, 432 uint32 hardware_delay_bytes, 433 double volume) { 434 // Mark data as active to ensure that the periodic calls to 435 // DoCheckForNoData() does not report an error to the event handler. 436 SetDataIsActive(true); 437 438 { 439 base::AutoLock auto_lock(lock_); 440 if (state_ != RECORDING) 441 return; 442 } 443 444 bool key_pressed = false; 445 if (user_input_monitor_) { 446 size_t current_count = user_input_monitor_->GetKeyPressCount(); 447 key_pressed = current_count != prev_key_down_count_; 448 prev_key_down_count_ = current_count; 449 DVLOG_IF(6, key_pressed) << "Detected keypress."; 450 } 451 452 // Use SharedMemory and SyncSocket if the client has created a SyncWriter. 453 // Used by all low-latency clients except WebSpeech. 454 if (SharedMemoryAndSyncSocketMode()) { 455 sync_writer_->Write(source, volume, key_pressed); 456 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); 457 458#if defined(AUDIO_POWER_MONITORING) 459 // Only do power-level measurements if an AudioPowerMonitor object has 460 // been created. Done in DoCreate() but not DoCreateForStream(), hence 461 // logging will mainly be done for WebRTC and WebSpeech clients. 462 if (!audio_level_) 463 return; 464 465 // Perform periodic audio (power) level measurements. 466 if ((base::TimeTicks::Now() - last_audio_level_log_time_).InSeconds() > 467 kPowerMonitorLogIntervalSeconds) { 468 // Wrap data into an AudioBus to match AudioPowerMonitor::Scan. 469 // TODO(henrika): remove this section when capture side uses AudioBus. 470 // See http://crbug.com/375155 for details. 471 audio_level_->Scan(*source, source->frames()); 472 473 // Get current average power level and add it to the log. 474 // Possible range is given by [-inf, 0] dBFS. 475 std::pair<float, bool> result = audio_level_->ReadCurrentPowerAndClip(); 476 477 // Use event handler on the audio thread to relay a message to the ARIH 478 // in content which does the actual logging on the IO thread. 479 task_runner_->PostTask( 480 FROM_HERE, 481 base::Bind( 482 &AudioInputController::DoLogAudioLevel, this, result.first)); 483 484 last_audio_level_log_time_ = base::TimeTicks::Now(); 485 486 // Reset the average power level (since we don't log continuously). 487 audio_level_->Reset(); 488 } 489#endif 490 return; 491 } 492 493 // TODO(henrika): Investigate if we can avoid the extra copy here. 494 // (see http://crbug.com/249316 for details). AFAIK, this scope is only 495 // active for WebSpeech clients. 496 scoped_ptr<AudioBus> audio_data = 497 AudioBus::Create(source->channels(), source->frames()); 498 source->CopyTo(audio_data.get()); 499 500 // Ownership of the audio buffer will be with the callback until it is run, 501 // when ownership is passed to the callback function. 502 task_runner_->PostTask( 503 FROM_HERE, 504 base::Bind( 505 &AudioInputController::DoOnData, this, base::Passed(&audio_data))); 506} 507 508void AudioInputController::DoOnData(scoped_ptr<AudioBus> data) { 509 DCHECK(task_runner_->BelongsToCurrentThread()); 510 if (handler_) 511 handler_->OnData(this, data.get()); 512} 513 514void AudioInputController::DoLogAudioLevel(float level_dbfs) { 515#if defined(AUDIO_POWER_MONITORING) 516 DCHECK(task_runner_->BelongsToCurrentThread()); 517 if (!handler_) 518 return; 519 520 std::string log_string = base::StringPrintf( 521 "AIC::OnData: average audio level=%.2f dBFS", level_dbfs); 522 static const float kSilenceThresholdDBFS = -72.24719896f; 523 if (level_dbfs < kSilenceThresholdDBFS) 524 log_string += " <=> no audio input!"; 525 handler_->OnLog(this, log_string); 526 527 UpdateSilenceState(level_dbfs < kSilenceThresholdDBFS); 528#endif 529} 530 531void AudioInputController::OnError(AudioInputStream* stream) { 532 // Handle error on the audio-manager thread. 533 task_runner_->PostTask(FROM_HERE, base::Bind( 534 &AudioInputController::DoReportError, this)); 535} 536 537void AudioInputController::DoStopCloseAndClearStream() { 538 DCHECK(task_runner_->BelongsToCurrentThread()); 539 540 // Allow calling unconditionally and bail if we don't have a stream to close. 541 if (stream_ != NULL) { 542 stream_->Stop(); 543 stream_->Close(); 544 stream_ = NULL; 545 } 546 547 // The event handler should not be touched after the stream has been closed. 548 handler_ = NULL; 549} 550 551void AudioInputController::SetDataIsActive(bool enabled) { 552 base::subtle::Release_Store(&data_is_active_, enabled); 553} 554 555bool AudioInputController::GetDataIsActive() { 556 return (base::subtle::Acquire_Load(&data_is_active_) != false); 557} 558 559#if defined(AUDIO_POWER_MONITORING) 560void AudioInputController::UpdateSilenceState(bool silence) { 561 if (silence) { 562 if (silence_state_ == SILENCE_STATE_NO_MEASUREMENT) { 563 silence_state_ = SILENCE_STATE_ONLY_SILENCE; 564 } else if (silence_state_ == SILENCE_STATE_ONLY_AUDIO) { 565 silence_state_ = SILENCE_STATE_AUDIO_AND_SILENCE; 566 } else { 567 DCHECK(silence_state_ == SILENCE_STATE_ONLY_SILENCE || 568 silence_state_ == SILENCE_STATE_AUDIO_AND_SILENCE); 569 } 570 } else { 571 if (silence_state_ == SILENCE_STATE_NO_MEASUREMENT) { 572 silence_state_ = SILENCE_STATE_ONLY_AUDIO; 573 } else if (silence_state_ == SILENCE_STATE_ONLY_SILENCE) { 574 silence_state_ = SILENCE_STATE_AUDIO_AND_SILENCE; 575 } else { 576 DCHECK(silence_state_ == SILENCE_STATE_ONLY_AUDIO || 577 silence_state_ == SILENCE_STATE_AUDIO_AND_SILENCE); 578 } 579 } 580} 581 582void AudioInputController::LogSilenceState(SilenceState value) { 583 UMA_HISTOGRAM_ENUMERATION("Media.AudioInputControllerSessionSilenceReport", 584 value, 585 SILENCE_STATE_MAX + 1); 586} 587#endif 588 589} // namespace media 590