| 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/audio_input_controller.h" | 5 #include "media/audio/audio_input_controller.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/threading/thread_restrictions.h" | 8 #include "base/threading/thread_restrictions.h" |
| 9 #include "media/base/limits.h" | 9 #include "media/base/limits.h" |
| 10 #include "media/base/scoped_histogram_timer.h" | 10 #include "media/base/scoped_histogram_timer.h" |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 DCHECK(!no_data_timer_.get()); | 205 DCHECK(!no_data_timer_.get()); |
| 206 | 206 |
| 207 // The timer is enabled for logging purposes. The NO_DATA_ERROR triggered | 207 // The timer is enabled for logging purposes. The NO_DATA_ERROR triggered |
| 208 // from the timer must be ignored by the EventHandler. | 208 // from the timer must be ignored by the EventHandler. |
| 209 // TODO(henrika): remove usage of timer when it has been verified on Canary | 209 // TODO(henrika): remove usage of timer when it has been verified on Canary |
| 210 // that we are safe doing so. Goal is to get rid of |no_data_timer_| and | 210 // that we are safe doing so. Goal is to get rid of |no_data_timer_| and |
| 211 // everything that is tied to it. crbug.com/357569. | 211 // everything that is tied to it. crbug.com/357569. |
| 212 enable_nodata_timer = true; | 212 enable_nodata_timer = true; |
| 213 | 213 |
| 214 if (enable_nodata_timer) { | 214 if (enable_nodata_timer) { |
| 215 // Create the data timer which will call DoCheckForNoData(). The timer | 215 // Create the data timer which will call FirstCheckForNoData(). The timer |
| 216 // is started in DoRecord() and restarted in each DoCheckForNoData() | 216 // is started in DoRecord() and restarted in each DoCheckForNoData() |
| 217 // callback. | 217 // callback. |
| 218 no_data_timer_.reset(new base::Timer( | 218 no_data_timer_.reset(new base::Timer( |
| 219 FROM_HERE, base::TimeDelta::FromSeconds(kTimerInitialIntervalSeconds), | 219 FROM_HERE, base::TimeDelta::FromSeconds(kTimerInitialIntervalSeconds), |
| 220 base::Bind(&AudioInputController::DoCheckForNoData, | 220 base::Bind(&AudioInputController::FirstCheckForNoData, |
| 221 base::Unretained(this)), false)); | 221 base::Unretained(this)), false)); |
| 222 } else { | 222 } else { |
| 223 DVLOG(1) << "Disabled: timer check for no data."; | 223 DVLOG(1) << "Disabled: timer check for no data."; |
| 224 } | 224 } |
| 225 | 225 |
| 226 state_ = CREATED; | 226 state_ = CREATED; |
| 227 if (handler_) | 227 if (handler_) |
| 228 handler_->OnCreated(this); | 228 handler_->OnCreated(this); |
| 229 | 229 |
| 230 if (user_input_monitor_) { | 230 if (user_input_monitor_) { |
| 231 user_input_monitor_->EnableKeyPressMonitoring(); | 231 user_input_monitor_->EnableKeyPressMonitoring(); |
| 232 prev_key_down_count_ = user_input_monitor_->GetKeyPressCount(); | 232 prev_key_down_count_ = user_input_monitor_->GetKeyPressCount(); |
| 233 } | 233 } |
| 234 } | 234 } |
| 235 | 235 |
| 236 void AudioInputController::DoRecord() { | 236 void AudioInputController::DoRecord() { |
| 237 DCHECK(task_runner_->BelongsToCurrentThread()); | 237 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 238 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.RecordTime"); | 238 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.RecordTime"); |
| 239 | 239 |
| 240 if (state_ != CREATED) | 240 if (state_ != CREATED) |
| 241 return; | 241 return; |
| 242 | 242 |
| 243 { | 243 { |
| 244 base::AutoLock auto_lock(lock_); | 244 base::AutoLock auto_lock(lock_); |
| 245 state_ = RECORDING; | 245 state_ = RECORDING; |
| 246 } | 246 } |
| 247 | 247 |
| 248 if (no_data_timer_) { | 248 if (no_data_timer_) { |
| 249 // Start the data timer. Once |kTimerResetIntervalSeconds| have passed, | 249 // Start the data timer. Once |kTimerResetIntervalSeconds| have passed, |
| 250 // a callback to DoCheckForNoData() is made. | 250 // a callback to FirstCheckForNoData() is made. |
| 251 no_data_timer_->Reset(); | 251 no_data_timer_->Reset(); |
| 252 } | 252 } |
| 253 | 253 |
| 254 stream_->Start(this); | 254 stream_->Start(this); |
| 255 if (handler_) | 255 if (handler_) |
| 256 handler_->OnRecording(this); | 256 handler_->OnRecording(this); |
| 257 } | 257 } |
| 258 | 258 |
| 259 void AudioInputController::DoClose() { | 259 void AudioInputController::DoClose() { |
| 260 DCHECK(task_runner_->BelongsToCurrentThread()); | 260 DCHECK(task_runner_->BelongsToCurrentThread()); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 DCHECK(task_runner_->BelongsToCurrentThread()); | 311 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 312 DCHECK_NE(state_, RECORDING); | 312 DCHECK_NE(state_, RECORDING); |
| 313 | 313 |
| 314 // Ensure that the AGC state only can be modified before streaming starts. | 314 // Ensure that the AGC state only can be modified before streaming starts. |
| 315 if (state_ != CREATED) | 315 if (state_ != CREATED) |
| 316 return; | 316 return; |
| 317 | 317 |
| 318 stream_->SetAutomaticGainControl(enabled); | 318 stream_->SetAutomaticGainControl(enabled); |
| 319 } | 319 } |
| 320 | 320 |
| 321 void AudioInputController::FirstCheckForNoData() { |
| 322 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 323 UMA_HISTOGRAM_BOOLEAN("Media.AudioInputControllerCaptureStartupSuccess", |
| 324 GetDataIsActive()); |
| 325 DoCheckForNoData(); |
| 326 } |
| 327 |
| 321 void AudioInputController::DoCheckForNoData() { | 328 void AudioInputController::DoCheckForNoData() { |
| 322 DCHECK(task_runner_->BelongsToCurrentThread()); | 329 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 323 | 330 |
| 324 if (!GetDataIsActive()) { | 331 if (!GetDataIsActive()) { |
| 325 // The data-is-active marker will be false only if it has been more than | 332 // The data-is-active marker will be false only if it has been more than |
| 326 // one second since a data packet was recorded. This can happen if a | 333 // one second since a data packet was recorded. This can happen if a |
| 327 // capture device has been removed or disabled. | 334 // capture device has been removed or disabled. |
| 328 if (handler_) | 335 if (handler_) |
| 329 handler_->OnError(this, NO_DATA_ERROR); | 336 handler_->OnError(this, NO_DATA_ERROR); |
| 330 } | 337 } |
| 331 | 338 |
| 332 // Mark data as non-active. The flag will be re-enabled in OnData() each | 339 // Mark data as non-active. The flag will be re-enabled in OnData() each |
| 333 // time a data packet is received. Hence, under normal conditions, the | 340 // time a data packet is received. Hence, under normal conditions, the |
| 334 // flag will only be disabled during a very short period. | 341 // flag will only be disabled during a very short period. |
| 335 SetDataIsActive(false); | 342 SetDataIsActive(false); |
| 336 | 343 |
| 337 // Restart the timer to ensure that we check the flag again in | 344 // Restart the timer to ensure that we check the flag again in |
| 338 // |kTimerResetIntervalSeconds|. | 345 // |kTimerResetIntervalSeconds|. |
| 339 no_data_timer_->Start( | 346 no_data_timer_->Start( |
| 340 FROM_HERE, base::TimeDelta::FromSeconds(kTimerResetIntervalSeconds), | 347 FROM_HERE, base::TimeDelta::FromSeconds(kTimerResetIntervalSeconds), |
| 341 base::Bind(&AudioInputController::DoCheckForNoData, | 348 base::Bind(&AudioInputController::DoCheckForNoData, |
| 342 base::Unretained(this))); | 349 base::Unretained(this))); |
| 343 } | 350 } |
| 344 | 351 |
| 345 void AudioInputController::OnData(AudioInputStream* stream, | 352 void AudioInputController::OnData(AudioInputStream* stream, |
| 346 const uint8* data, | 353 const uint8* data, |
| 347 uint32 size, | 354 uint32 size, |
| 348 uint32 hardware_delay_bytes, | 355 uint32 hardware_delay_bytes, |
| 349 double volume) { | 356 double volume) { |
| 357 // Mark data as active to ensure that the periodic calls to |
| 358 // DoCheckForNoData() does not report an error to the event handler. |
| 359 SetDataIsActive(true); |
| 360 |
| 350 { | 361 { |
| 351 base::AutoLock auto_lock(lock_); | 362 base::AutoLock auto_lock(lock_); |
| 352 if (state_ != RECORDING) | 363 if (state_ != RECORDING) |
| 353 return; | 364 return; |
| 354 } | 365 } |
| 355 | 366 |
| 356 bool key_pressed = false; | 367 bool key_pressed = false; |
| 357 if (user_input_monitor_) { | 368 if (user_input_monitor_) { |
| 358 size_t current_count = user_input_monitor_->GetKeyPressCount(); | 369 size_t current_count = user_input_monitor_->GetKeyPressCount(); |
| 359 key_pressed = current_count != prev_key_down_count_; | 370 key_pressed = current_count != prev_key_down_count_; |
| 360 prev_key_down_count_ = current_count; | 371 prev_key_down_count_ = current_count; |
| 361 DVLOG_IF(6, key_pressed) << "Detected keypress."; | 372 DVLOG_IF(6, key_pressed) << "Detected keypress."; |
| 362 } | 373 } |
| 363 | 374 |
| 364 // Mark data as active to ensure that the periodic calls to | |
| 365 // DoCheckForNoData() does not report an error to the event handler. | |
| 366 SetDataIsActive(true); | |
| 367 | |
| 368 // Use SharedMemory and SyncSocket if the client has created a SyncWriter. | 375 // Use SharedMemory and SyncSocket if the client has created a SyncWriter. |
| 369 // Used by all low-latency clients except WebSpeech. | 376 // Used by all low-latency clients except WebSpeech. |
| 370 if (SharedMemoryAndSyncSocketMode()) { | 377 if (SharedMemoryAndSyncSocketMode()) { |
| 371 sync_writer_->Write(data, size, volume, key_pressed); | 378 sync_writer_->Write(data, size, volume, key_pressed); |
| 372 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); | 379 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); |
| 373 return; | 380 return; |
| 374 } | 381 } |
| 375 | 382 |
| 376 // TODO(henrika): Investigate if we can avoid the extra copy here. | 383 // TODO(henrika): Investigate if we can avoid the extra copy here. |
| 377 // (see http://crbug.com/249316 for details). AFAIK, this scope is only | 384 // (see http://crbug.com/249316 for details). AFAIK, this scope is only |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 413 | 420 |
| 414 void AudioInputController::SetDataIsActive(bool enabled) { | 421 void AudioInputController::SetDataIsActive(bool enabled) { |
| 415 base::subtle::Release_Store(&data_is_active_, enabled); | 422 base::subtle::Release_Store(&data_is_active_, enabled); |
| 416 } | 423 } |
| 417 | 424 |
| 418 bool AudioInputController::GetDataIsActive() { | 425 bool AudioInputController::GetDataIsActive() { |
| 419 return (base::subtle::Acquire_Load(&data_is_active_) != false); | 426 return (base::subtle::Acquire_Load(&data_is_active_) != false); |
| 420 } | 427 } |
| 421 | 428 |
| 422 } // namespace media | 429 } // namespace media |
| OLD | NEW |