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 |