| 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 } | 78 } |
| 79 #endif // AUDIO_POWER_MONITORING | 79 #endif // AUDIO_POWER_MONITORING |
| 80 | 80 |
| 81 } // namespace | 81 } // namespace |
| 82 | 82 |
| 83 namespace media { | 83 namespace media { |
| 84 | 84 |
| 85 // static | 85 // static |
| 86 AudioInputController::Factory* AudioInputController::factory_ = nullptr; | 86 AudioInputController::Factory* AudioInputController::factory_ = nullptr; |
| 87 | 87 |
| 88 AudioInputController::AudioInputController(EventHandler* handler, | 88 AudioInputController::AudioInputController( |
| 89 SyncWriter* sync_writer, | 89 EventHandler* handler, |
| 90 UserInputMonitor* user_input_monitor, | 90 SyncWriter* sync_writer, |
| 91 const bool agc_is_enabled) | 91 std::unique_ptr<AudioInputWriter> debug_writer, |
| 92 UserInputMonitor* user_input_monitor, |
| 93 const bool agc_is_enabled) |
| 92 : creator_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 94 : creator_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 93 handler_(handler), | 95 handler_(handler), |
| 94 stream_(nullptr), | 96 stream_(nullptr), |
| 95 should_report_stats(0), | 97 should_report_stats(0), |
| 96 state_(CLOSED), | 98 state_(CLOSED), |
| 97 sync_writer_(sync_writer), | 99 sync_writer_(sync_writer), |
| 98 max_volume_(0.0), | 100 max_volume_(0.0), |
| 99 user_input_monitor_(user_input_monitor), | 101 user_input_monitor_(user_input_monitor), |
| 100 agc_is_enabled_(agc_is_enabled), | 102 agc_is_enabled_(agc_is_enabled), |
| 101 #if defined(AUDIO_POWER_MONITORING) | 103 #if defined(AUDIO_POWER_MONITORING) |
| 102 power_measurement_is_enabled_(false), | 104 power_measurement_is_enabled_(false), |
| 103 log_silence_state_(false), | 105 log_silence_state_(false), |
| 104 silence_state_(SILENCE_STATE_NO_MEASUREMENT), | 106 silence_state_(SILENCE_STATE_NO_MEASUREMENT), |
| 105 #endif | 107 #endif |
| 106 prev_key_down_count_(0), | 108 prev_key_down_count_(0), |
| 107 input_writer_(nullptr) { | 109 debug_writer_(std::move(debug_writer)) { |
| 108 DCHECK(creator_task_runner_.get()); | 110 DCHECK(creator_task_runner_.get()); |
| 109 } | 111 } |
| 110 | 112 |
| 111 AudioInputController::~AudioInputController() { | 113 AudioInputController::~AudioInputController() { |
| 112 DCHECK_EQ(state_, CLOSED); | 114 DCHECK_EQ(state_, CLOSED); |
| 113 } | 115 } |
| 114 | 116 |
| 115 // static | 117 // static |
| 116 scoped_refptr<AudioInputController> AudioInputController::Create( | 118 scoped_refptr<AudioInputController> AudioInputController::Create( |
| 117 AudioManager* audio_manager, | 119 AudioManager* audio_manager, |
| 118 EventHandler* event_handler, | 120 EventHandler* event_handler, |
| 119 const AudioParameters& params, | 121 const AudioParameters& params, |
| 120 const std::string& device_id, | 122 const std::string& device_id, |
| 121 UserInputMonitor* user_input_monitor) { | 123 UserInputMonitor* user_input_monitor) { |
| 122 DCHECK(audio_manager); | 124 DCHECK(audio_manager); |
| 123 | 125 |
| 124 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) | 126 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) |
| 125 return nullptr; | 127 return nullptr; |
| 126 | 128 |
| 127 if (factory_) { | 129 if (factory_) { |
| 128 return factory_->Create( | 130 return factory_->Create( |
| 129 audio_manager, event_handler, params, user_input_monitor); | 131 audio_manager, event_handler, params, user_input_monitor); |
| 130 } | 132 } |
| 131 scoped_refptr<AudioInputController> controller(new AudioInputController( | 133 scoped_refptr<AudioInputController> controller(new AudioInputController( |
| 132 event_handler, nullptr, user_input_monitor, false)); | 134 event_handler, nullptr, nullptr, user_input_monitor, false)); |
| 133 | 135 |
| 134 controller->task_runner_ = audio_manager->GetTaskRunner(); | 136 controller->task_runner_ = audio_manager->GetTaskRunner(); |
| 135 | 137 |
| 136 // Create and open a new audio input stream from the existing | 138 // Create and open a new audio input stream from the existing |
| 137 // audio-device thread. | 139 // audio-device thread. |
| 138 if (!controller->task_runner_->PostTask( | 140 if (!controller->task_runner_->PostTask( |
| 139 FROM_HERE, | 141 FROM_HERE, |
| 140 base::Bind(&AudioInputController::DoCreate, | 142 base::Bind(&AudioInputController::DoCreate, |
| 141 controller, | 143 controller, |
| 142 base::Unretained(audio_manager), | 144 base::Unretained(audio_manager), |
| 143 params, | 145 params, |
| 144 device_id))) { | 146 device_id))) { |
| 145 controller = nullptr; | 147 controller = nullptr; |
| 146 } | 148 } |
| 147 | 149 |
| 148 return controller; | 150 return controller; |
| 149 } | 151 } |
| 150 | 152 |
| 151 // static | 153 // static |
| 152 scoped_refptr<AudioInputController> AudioInputController::CreateLowLatency( | 154 scoped_refptr<AudioInputController> AudioInputController::CreateLowLatency( |
| 153 AudioManager* audio_manager, | 155 AudioManager* audio_manager, |
| 154 EventHandler* event_handler, | 156 EventHandler* event_handler, |
| 155 const AudioParameters& params, | 157 const AudioParameters& params, |
| 156 const std::string& device_id, | 158 const std::string& device_id, |
| 157 SyncWriter* sync_writer, | 159 SyncWriter* sync_writer, |
| 160 std::unique_ptr<AudioInputWriter> debug_writer, |
| 158 UserInputMonitor* user_input_monitor, | 161 UserInputMonitor* user_input_monitor, |
| 159 const bool agc_is_enabled) { | 162 const bool agc_is_enabled) { |
| 160 DCHECK(audio_manager); | 163 DCHECK(audio_manager); |
| 161 DCHECK(sync_writer); | 164 DCHECK(sync_writer); |
| 162 | 165 |
| 163 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) | 166 if (!params.IsValid() || (params.channels() > kMaxInputChannels)) |
| 164 return nullptr; | 167 return nullptr; |
| 165 | 168 |
| 166 // Create the AudioInputController object and ensure that it runs on | 169 // Create the AudioInputController object and ensure that it runs on |
| 167 // the audio-manager thread. | 170 // the audio-manager thread. |
| 168 scoped_refptr<AudioInputController> controller(new AudioInputController( | 171 scoped_refptr<AudioInputController> controller(new AudioInputController( |
| 169 event_handler, sync_writer, user_input_monitor, agc_is_enabled)); | 172 event_handler, sync_writer, std::move(debug_writer), user_input_monitor, |
| 173 agc_is_enabled)); |
| 170 controller->task_runner_ = audio_manager->GetTaskRunner(); | 174 controller->task_runner_ = audio_manager->GetTaskRunner(); |
| 171 | 175 |
| 172 // Create and open a new audio input stream from the existing | 176 // Create and open a new audio input stream from the existing |
| 173 // audio-device thread. Use the provided audio-input device. | 177 // audio-device thread. Use the provided audio-input device. |
| 174 if (!controller->task_runner_->PostTask( | 178 if (!controller->task_runner_->PostTask( |
| 175 FROM_HERE, | 179 FROM_HERE, |
| 176 base::Bind(&AudioInputController::DoCreateForLowLatency, | 180 base::Bind(&AudioInputController::DoCreateForLowLatency, |
| 177 controller, | 181 controller, |
| 178 base::Unretained(audio_manager), | 182 base::Unretained(audio_manager), |
| 179 params, | 183 params, |
| 180 device_id))) { | 184 device_id))) { |
| 181 controller = nullptr; | 185 controller = nullptr; |
| 182 } | 186 } |
| 183 | 187 |
| 184 return controller; | 188 return controller; |
| 185 } | 189 } |
| 186 | 190 |
| 187 // static | 191 // static |
| 188 scoped_refptr<AudioInputController> AudioInputController::CreateForStream( | 192 scoped_refptr<AudioInputController> AudioInputController::CreateForStream( |
| 189 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 193 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
| 190 EventHandler* event_handler, | 194 EventHandler* event_handler, |
| 191 AudioInputStream* stream, | 195 AudioInputStream* stream, |
| 192 SyncWriter* sync_writer, | 196 SyncWriter* sync_writer, |
| 197 std::unique_ptr<AudioInputWriter> debug_writer, |
| 193 UserInputMonitor* user_input_monitor) { | 198 UserInputMonitor* user_input_monitor) { |
| 194 DCHECK(sync_writer); | 199 DCHECK(sync_writer); |
| 195 DCHECK(stream); | 200 DCHECK(stream); |
| 196 | 201 |
| 197 // Create the AudioInputController object and ensure that it runs on | 202 // Create the AudioInputController object and ensure that it runs on |
| 198 // the audio-manager thread. | 203 // the audio-manager thread. |
| 199 scoped_refptr<AudioInputController> controller(new AudioInputController( | 204 scoped_refptr<AudioInputController> controller(new AudioInputController( |
| 200 event_handler, sync_writer, user_input_monitor, false)); | 205 event_handler, sync_writer, std::move(debug_writer), user_input_monitor, |
| 206 false)); |
| 201 controller->task_runner_ = task_runner; | 207 controller->task_runner_ = task_runner; |
| 202 | 208 |
| 203 if (!controller->task_runner_->PostTask( | 209 if (!controller->task_runner_->PostTask( |
| 204 FROM_HERE, | 210 FROM_HERE, |
| 205 base::Bind(&AudioInputController::DoCreateForStream, | 211 base::Bind(&AudioInputController::DoCreateForStream, |
| 206 controller, | 212 controller, |
| 207 stream))) { | 213 stream))) { |
| 208 controller = nullptr; | 214 controller = nullptr; |
| 209 } | 215 } |
| 210 | 216 |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 367 if (user_input_monitor_) | 373 if (user_input_monitor_) |
| 368 user_input_monitor_->DisableKeyPressMonitoring(); | 374 user_input_monitor_->DisableKeyPressMonitoring(); |
| 369 | 375 |
| 370 #if defined(AUDIO_POWER_MONITORING) | 376 #if defined(AUDIO_POWER_MONITORING) |
| 371 // Send UMA stats if enabled. | 377 // Send UMA stats if enabled. |
| 372 if (log_silence_state_) | 378 if (log_silence_state_) |
| 373 LogSilenceState(silence_state_); | 379 LogSilenceState(silence_state_); |
| 374 log_silence_state_ = false; | 380 log_silence_state_ = false; |
| 375 #endif | 381 #endif |
| 376 | 382 |
| 377 input_writer_ = nullptr; | 383 if (debug_writer_) |
| 384 debug_writer_->Stop(); |
| 378 | 385 |
| 379 state_ = CLOSED; | 386 state_ = CLOSED; |
| 380 } | 387 } |
| 381 | 388 |
| 382 void AudioInputController::DoReportError() { | 389 void AudioInputController::DoReportError() { |
| 383 DCHECK(task_runner_->BelongsToCurrentThread()); | 390 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 384 if (handler_) | 391 if (handler_) |
| 385 handler_->OnError(this, STREAM_ERROR); | 392 handler_->OnError(this, STREAM_ERROR); |
| 386 } | 393 } |
| 387 | 394 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 405 } | 412 } |
| 406 | 413 |
| 407 // Set the stream volume and scale to a range matched to the platform. | 414 // Set the stream volume and scale to a range matched to the platform. |
| 408 stream_->SetVolume(max_volume_ * volume); | 415 stream_->SetVolume(max_volume_ * volume); |
| 409 } | 416 } |
| 410 | 417 |
| 411 void AudioInputController::OnData(AudioInputStream* stream, | 418 void AudioInputController::OnData(AudioInputStream* stream, |
| 412 const AudioBus* source, | 419 const AudioBus* source, |
| 413 uint32_t hardware_delay_bytes, | 420 uint32_t hardware_delay_bytes, |
| 414 double volume) { | 421 double volume) { |
| 415 // |input_writer_| should only be accessed on the audio thread, but as a means | 422 if (debug_writer_ && debug_writer_->WillWrite()) { |
| 416 // to avoid copying data and posting on the audio thread, we just check for | |
| 417 // non-null here. | |
| 418 if (input_writer_) { | |
| 419 std::unique_ptr<AudioBus> source_copy = | 423 std::unique_ptr<AudioBus> source_copy = |
| 420 AudioBus::Create(source->channels(), source->frames()); | 424 AudioBus::Create(source->channels(), source->frames()); |
| 421 source->CopyTo(source_copy.get()); | 425 source->CopyTo(source_copy.get()); |
| 422 task_runner_->PostTask( | 426 task_runner_->PostTask( |
| 423 FROM_HERE, | 427 FROM_HERE, |
| 424 base::Bind( | 428 base::Bind( |
| 425 &AudioInputController::WriteInputDataForDebugging, | 429 &AudioInputController::WriteInputDataForDebugging, |
| 426 this, | 430 this, |
| 427 base::Passed(&source_copy))); | 431 base::Passed(&source_copy))); |
| 428 } | 432 } |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 537 #endif | 541 #endif |
| 538 } | 542 } |
| 539 | 543 |
| 540 void AudioInputController::OnError(AudioInputStream* stream) { | 544 void AudioInputController::OnError(AudioInputStream* stream) { |
| 541 // Handle error on the audio-manager thread. | 545 // Handle error on the audio-manager thread. |
| 542 task_runner_->PostTask(FROM_HERE, base::Bind( | 546 task_runner_->PostTask(FROM_HERE, base::Bind( |
| 543 &AudioInputController::DoReportError, this)); | 547 &AudioInputController::DoReportError, this)); |
| 544 } | 548 } |
| 545 | 549 |
| 546 void AudioInputController::EnableDebugRecording( | 550 void AudioInputController::EnableDebugRecording( |
| 547 AudioInputWriter* input_writer) { | 551 const base::FilePath& file_name) { |
| 548 task_runner_->PostTask(FROM_HERE, base::Bind( | 552 task_runner_->PostTask( |
| 549 &AudioInputController::DoEnableDebugRecording, | 553 FROM_HERE, base::Bind(&AudioInputController::DoEnableDebugRecording, this, |
| 550 this, | 554 file_name)); |
| 551 input_writer)); | |
| 552 } | 555 } |
| 553 | 556 |
| 554 void AudioInputController::DisableDebugRecording( | 557 void AudioInputController::DisableDebugRecording() { |
| 555 const base::Closure& callback) { | |
| 556 DCHECK(creator_task_runner_->BelongsToCurrentThread()); | 558 DCHECK(creator_task_runner_->BelongsToCurrentThread()); |
| 557 DCHECK(!callback.is_null()); | 559 task_runner_->PostTask( |
| 558 | |
| 559 task_runner_->PostTaskAndReply( | |
| 560 FROM_HERE, | 560 FROM_HERE, |
| 561 base::Bind(&AudioInputController::DoDisableDebugRecording, | 561 base::Bind(&AudioInputController::DoDisableDebugRecording, this)); |
| 562 this), | |
| 563 callback); | |
| 564 } | 562 } |
| 565 | 563 |
| 566 void AudioInputController::DoStopCloseAndClearStream() { | 564 void AudioInputController::DoStopCloseAndClearStream() { |
| 567 DCHECK(task_runner_->BelongsToCurrentThread()); | 565 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 568 | 566 |
| 569 // Allow calling unconditionally and bail if we don't have a stream to close. | 567 // Allow calling unconditionally and bail if we don't have a stream to close. |
| 570 if (stream_ != nullptr) { | 568 if (stream_ != nullptr) { |
| 571 stream_->Stop(); | 569 stream_->Stop(); |
| 572 stream_->Close(); | 570 stream_->Close(); |
| 573 stream_ = nullptr; | 571 stream_ = nullptr; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 614 // after initialization. To avoid underflow, we | 612 // after initialization. To avoid underflow, we |
| 615 // also check if should_report_stats is one before decrementing. | 613 // also check if should_report_stats is one before decrementing. |
| 616 if (base::AtomicRefCountIsOne(&should_report_stats) && | 614 if (base::AtomicRefCountIsOne(&should_report_stats) && |
| 617 !base::AtomicRefCountDec(&should_report_stats)) { | 615 !base::AtomicRefCountDec(&should_report_stats)) { |
| 618 UMA_HISTOGRAM_ENUMERATION("Media.AudioInputControllerCaptureStartupSuccess", | 616 UMA_HISTOGRAM_ENUMERATION("Media.AudioInputControllerCaptureStartupSuccess", |
| 619 result, CAPTURE_STARTUP_RESULT_MAX + 1); | 617 result, CAPTURE_STARTUP_RESULT_MAX + 1); |
| 620 } | 618 } |
| 621 } | 619 } |
| 622 | 620 |
| 623 void AudioInputController::DoEnableDebugRecording( | 621 void AudioInputController::DoEnableDebugRecording( |
| 624 AudioInputWriter* input_writer) { | 622 const base::FilePath& file_name) { |
| 625 DCHECK(task_runner_->BelongsToCurrentThread()); | 623 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 626 DCHECK(!input_writer_); | 624 if (debug_writer_) |
| 627 input_writer_ = input_writer; | 625 debug_writer_->Start(file_name); |
| 628 } | 626 } |
| 629 | 627 |
| 630 void AudioInputController::DoDisableDebugRecording() { | 628 void AudioInputController::DoDisableDebugRecording() { |
| 631 DCHECK(task_runner_->BelongsToCurrentThread()); | 629 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 632 input_writer_ = nullptr; | 630 if (debug_writer_) |
| 631 debug_writer_->Stop(); |
| 633 } | 632 } |
| 634 | 633 |
| 635 void AudioInputController::WriteInputDataForDebugging( | 634 void AudioInputController::WriteInputDataForDebugging( |
| 636 std::unique_ptr<AudioBus> data) { | 635 std::unique_ptr<AudioBus> data) { |
| 637 DCHECK(task_runner_->BelongsToCurrentThread()); | 636 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 638 if (input_writer_) | 637 if (debug_writer_) |
| 639 input_writer_->Write(std::move(data)); | 638 debug_writer_->Write(std::move(data)); |
| 640 } | 639 } |
| 641 | 640 |
| 642 void AudioInputController::LogMessage(const std::string& message) { | 641 void AudioInputController::LogMessage(const std::string& message) { |
| 643 DCHECK(task_runner_->BelongsToCurrentThread()); | 642 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 644 handler_->OnLog(this, message); | 643 handler_->OnLog(this, message); |
| 645 } | 644 } |
| 646 | 645 |
| 647 } // namespace media | 646 } // namespace media |
| OLD | NEW |