| 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/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
| 9 #include "base/threading/thread_restrictions.h" | 9 #include "base/threading/thread_restrictions.h" |
| 10 #include "base/time/time.h" | 10 #include "base/time/time.h" |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 195 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CreateTime"); | 195 SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CreateTime"); |
| 196 | 196 |
| 197 #if defined(AUDIO_POWER_MONITORING) | 197 #if defined(AUDIO_POWER_MONITORING) |
| 198 // Create the audio (power) level meter given the provided audio parameters. | 198 // Create the audio (power) level meter given the provided audio parameters. |
| 199 // An AudioBus is also needed to wrap the raw data buffer from the native | 199 // An AudioBus is also needed to wrap the raw data buffer from the native |
| 200 // layer to match AudioPowerMonitor::Scan(). | 200 // layer to match AudioPowerMonitor::Scan(). |
| 201 // TODO(henrika): Remove use of extra AudioBus. See http://crbug.com/375155. | 201 // TODO(henrika): Remove use of extra AudioBus. See http://crbug.com/375155. |
| 202 audio_level_.reset(new media::AudioPowerMonitor( | 202 audio_level_.reset(new media::AudioPowerMonitor( |
| 203 params.sample_rate(), | 203 params.sample_rate(), |
| 204 TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMilliseconds))); | 204 TimeDelta::FromMilliseconds(kPowerMeasurementTimeConstantMilliseconds))); |
| 205 audio_bus_ = AudioBus::Create(params); |
| 205 audio_params_ = params; | 206 audio_params_ = params; |
| 206 #endif | 207 #endif |
| 207 | 208 |
| 208 // TODO(miu): See TODO at top of file. Until that's resolved, assume all | 209 // TODO(miu): See TODO at top of file. Until that's resolved, assume all |
| 209 // platform audio input requires the |no_data_timer_| be used to auto-detect | 210 // platform audio input requires the |no_data_timer_| be used to auto-detect |
| 210 // errors. In reality, probably only Windows needs to be treated as | 211 // errors. In reality, probably only Windows needs to be treated as |
| 211 // unreliable here. | 212 // unreliable here. |
| 212 DoCreateForStream(audio_manager->MakeAudioInputStream(params, device_id), | 213 DoCreateForStream(audio_manager->MakeAudioInputStream(params, device_id), |
| 213 true); | 214 true); |
| 214 } | 215 } |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 375 | 376 |
| 376 // Restart the timer to ensure that we check the flag again in | 377 // Restart the timer to ensure that we check the flag again in |
| 377 // |kTimerResetIntervalSeconds|. | 378 // |kTimerResetIntervalSeconds|. |
| 378 no_data_timer_->Start( | 379 no_data_timer_->Start( |
| 379 FROM_HERE, base::TimeDelta::FromSeconds(kTimerResetIntervalSeconds), | 380 FROM_HERE, base::TimeDelta::FromSeconds(kTimerResetIntervalSeconds), |
| 380 base::Bind(&AudioInputController::DoCheckForNoData, | 381 base::Bind(&AudioInputController::DoCheckForNoData, |
| 381 base::Unretained(this))); | 382 base::Unretained(this))); |
| 382 } | 383 } |
| 383 | 384 |
| 384 void AudioInputController::OnData(AudioInputStream* stream, | 385 void AudioInputController::OnData(AudioInputStream* stream, |
| 385 const AudioBus* source, | 386 const uint8* data, |
| 387 uint32 size, |
| 386 uint32 hardware_delay_bytes, | 388 uint32 hardware_delay_bytes, |
| 387 double volume) { | 389 double volume) { |
| 388 // Mark data as active to ensure that the periodic calls to | 390 // Mark data as active to ensure that the periodic calls to |
| 389 // DoCheckForNoData() does not report an error to the event handler. | 391 // DoCheckForNoData() does not report an error to the event handler. |
| 390 SetDataIsActive(true); | 392 SetDataIsActive(true); |
| 391 | 393 |
| 392 { | 394 { |
| 393 base::AutoLock auto_lock(lock_); | 395 base::AutoLock auto_lock(lock_); |
| 394 if (state_ != RECORDING) | 396 if (state_ != RECORDING) |
| 395 return; | 397 return; |
| 396 } | 398 } |
| 397 | 399 |
| 398 bool key_pressed = false; | 400 bool key_pressed = false; |
| 399 if (user_input_monitor_) { | 401 if (user_input_monitor_) { |
| 400 size_t current_count = user_input_monitor_->GetKeyPressCount(); | 402 size_t current_count = user_input_monitor_->GetKeyPressCount(); |
| 401 key_pressed = current_count != prev_key_down_count_; | 403 key_pressed = current_count != prev_key_down_count_; |
| 402 prev_key_down_count_ = current_count; | 404 prev_key_down_count_ = current_count; |
| 403 DVLOG_IF(6, key_pressed) << "Detected keypress."; | 405 DVLOG_IF(6, key_pressed) << "Detected keypress."; |
| 404 } | 406 } |
| 405 | 407 |
| 406 // Use SharedMemory and SyncSocket if the client has created a SyncWriter. | 408 // Use SharedMemory and SyncSocket if the client has created a SyncWriter. |
| 407 // Used by all low-latency clients except WebSpeech. | 409 // Used by all low-latency clients except WebSpeech. |
| 408 if (SharedMemoryAndSyncSocketMode()) { | 410 if (SharedMemoryAndSyncSocketMode()) { |
| 409 sync_writer_->Write(source, volume, key_pressed); | 411 sync_writer_->Write(data, size, volume, key_pressed); |
| 410 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); | 412 sync_writer_->UpdateRecordedBytes(hardware_delay_bytes); |
| 411 | 413 |
| 412 #if defined(AUDIO_POWER_MONITORING) | 414 #if defined(AUDIO_POWER_MONITORING) |
| 413 // Only do power-level measurements if an AudioPowerMonitor object has | 415 // Only do power-level measurements if an AudioPowerMonitor object has |
| 414 // been created. Done in DoCreate() but not DoCreateForStream(), hence | 416 // been created. Done in DoCreate() but not DoCreateForStream(), hence |
| 415 // logging will mainly be done for WebRTC and WebSpeech clients. | 417 // logging will mainly be done for WebRTC and WebSpeech clients. |
| 416 if (!audio_level_) | 418 if (!audio_level_) |
| 417 return; | 419 return; |
| 418 | 420 |
| 419 // Perform periodic audio (power) level measurements. | 421 // Perform periodic audio (power) level measurements. |
| 420 if ((base::TimeTicks::Now() - last_audio_level_log_time_).InSeconds() > | 422 if ((base::TimeTicks::Now() - last_audio_level_log_time_).InSeconds() > |
| 421 kPowerMonitorLogIntervalSeconds) { | 423 kPowerMonitorLogIntervalSeconds) { |
| 422 // Wrap data into an AudioBus to match AudioPowerMonitor::Scan. | 424 // Wrap data into an AudioBus to match AudioPowerMonitor::Scan. |
| 423 // TODO(henrika): remove this section when capture side uses AudioBus. | 425 // TODO(henrika): remove this section when capture side uses AudioBus. |
| 424 // See http://crbug.com/375155 for details. | 426 // See http://crbug.com/375155 for details. |
| 425 audio_level_->Scan(*source, source->frames()); | 427 audio_bus_->FromInterleaved( |
| 428 data, audio_bus_->frames(), audio_params_.bits_per_sample() / 8); |
| 429 audio_level_->Scan(*audio_bus_, audio_bus_->frames()); |
| 426 | 430 |
| 427 // Get current average power level and add it to the log. | 431 // Get current average power level and add it to the log. |
| 428 // Possible range is given by [-inf, 0] dBFS. | 432 // Possible range is given by [-inf, 0] dBFS. |
| 429 std::pair<float, bool> result = audio_level_->ReadCurrentPowerAndClip(); | 433 std::pair<float, bool> result = audio_level_->ReadCurrentPowerAndClip(); |
| 430 | 434 |
| 431 // Use event handler on the audio thread to relay a message to the ARIH | 435 // Use event handler on the audio thread to relay a message to the ARIH |
| 432 // in content which does the actual logging on the IO thread. | 436 // in content which does the actual logging on the IO thread. |
| 433 task_runner_->PostTask( | 437 task_runner_->PostTask( |
| 434 FROM_HERE, | 438 FROM_HERE, |
| 435 base::Bind( | 439 base::Bind( |
| 436 &AudioInputController::DoLogAudioLevel, this, result.first)); | 440 &AudioInputController::DoLogAudioLevel, this, result.first)); |
| 437 | 441 |
| 438 last_audio_level_log_time_ = base::TimeTicks::Now(); | 442 last_audio_level_log_time_ = base::TimeTicks::Now(); |
| 439 | 443 |
| 440 // Reset the average power level (since we don't log continuously). | 444 // Reset the average power level (since we don't log continuously). |
| 441 audio_level_->Reset(); | 445 audio_level_->Reset(); |
| 442 } | 446 } |
| 443 #endif | 447 #endif |
| 448 |
| 444 return; | 449 return; |
| 445 } | 450 } |
| 446 | 451 |
| 447 // TODO(henrika): Investigate if we can avoid the extra copy here. | 452 // TODO(henrika): Investigate if we can avoid the extra copy here. |
| 448 // (see http://crbug.com/249316 for details). AFAIK, this scope is only | 453 // (see http://crbug.com/249316 for details). AFAIK, this scope is only |
| 449 // active for WebSpeech clients. | 454 // active for WebSpeech clients. |
| 450 scoped_ptr<AudioBus> audio_data = | 455 scoped_ptr<uint8[]> audio_data(new uint8[size]); |
| 451 AudioBus::Create(source->channels(), source->frames()); | 456 memcpy(audio_data.get(), data, size); |
| 452 source->CopyTo(audio_data.get()); | |
| 453 | 457 |
| 454 // Ownership of the audio buffer will be with the callback until it is run, | 458 // Ownership of the audio buffer will be with the callback until it is run, |
| 455 // when ownership is passed to the callback function. | 459 // when ownership is passed to the callback function. |
| 456 task_runner_->PostTask( | 460 task_runner_->PostTask(FROM_HERE, base::Bind( |
| 457 FROM_HERE, | 461 &AudioInputController::DoOnData, this, base::Passed(&audio_data), size)); |
| 458 base::Bind( | |
| 459 &AudioInputController::DoOnData, this, base::Passed(&audio_data))); | |
| 460 } | 462 } |
| 461 | 463 |
| 462 void AudioInputController::DoOnData(scoped_ptr<AudioBus> data) { | 464 void AudioInputController::DoOnData(scoped_ptr<uint8[]> data, uint32 size) { |
| 463 DCHECK(task_runner_->BelongsToCurrentThread()); | 465 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 464 if (handler_) | 466 if (handler_) |
| 465 handler_->OnData(this, data.get()); | 467 handler_->OnData(this, data.get(), size); |
| 466 } | 468 } |
| 467 | 469 |
| 468 void AudioInputController::DoLogAudioLevel(float level_dbfs) { | 470 void AudioInputController::DoLogAudioLevel(float level_dbfs) { |
| 469 #if defined(AUDIO_POWER_MONITORING) | 471 #if defined(AUDIO_POWER_MONITORING) |
| 470 DCHECK(task_runner_->BelongsToCurrentThread()); | 472 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 471 if (!handler_) | 473 if (!handler_) |
| 472 return; | 474 return; |
| 473 | 475 |
| 474 std::string log_string = base::StringPrintf( | 476 std::string log_string = base::StringPrintf( |
| 475 "AIC::OnData: average audio level=%.2f dBFS", level_dbfs); | 477 "AIC::OnData: average audio level=%.2f dBFS", level_dbfs); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 503 | 505 |
| 504 void AudioInputController::SetDataIsActive(bool enabled) { | 506 void AudioInputController::SetDataIsActive(bool enabled) { |
| 505 base::subtle::Release_Store(&data_is_active_, enabled); | 507 base::subtle::Release_Store(&data_is_active_, enabled); |
| 506 } | 508 } |
| 507 | 509 |
| 508 bool AudioInputController::GetDataIsActive() { | 510 bool AudioInputController::GetDataIsActive() { |
| 509 return (base::subtle::Acquire_Load(&data_is_active_) != false); | 511 return (base::subtle::Acquire_Load(&data_is_active_) != false); |
| 510 } | 512 } |
| 511 | 513 |
| 512 } // namespace media | 514 } // namespace media |
| OLD | NEW |