| 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 "content/renderer/media/webrtc_audio_capturer.h" | 5 #include "content/renderer/media/webrtc_audio_capturer.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 | 23 |
| 24 namespace { | 24 namespace { |
| 25 | 25 |
| 26 // Time constant for AudioPowerMonitor. See AudioPowerMonitor ctor comments | 26 // Time constant for AudioPowerMonitor. See AudioPowerMonitor ctor comments |
| 27 // for semantics. This value was arbitrarily chosen, but seems to work well. | 27 // for semantics. This value was arbitrarily chosen, but seems to work well. |
| 28 const int kPowerMonitorTimeConstantMs = 10; | 28 const int kPowerMonitorTimeConstantMs = 10; |
| 29 | 29 |
| 30 // The time between two audio power level samples. | 30 // The time between two audio power level samples. |
| 31 const int kPowerMonitorLogIntervalSeconds = 10; | 31 const int kPowerMonitorLogIntervalSeconds = 10; |
| 32 | 32 |
| 33 // Method to check if any of the data in |audio_source| has energy. |
| 34 bool HasDataEnergy(const media::AudioBus& audio_source) { |
| 35 for (int ch = 0; ch < audio_source.channels(); ++ch) { |
| 36 const float* channel_ptr = audio_source.channel(ch); |
| 37 for (int frame = 0; frame < audio_source.frames(); ++frame) { |
| 38 if (channel_ptr[frame] != 0) |
| 39 return true; |
| 40 } |
| 41 } |
| 42 |
| 43 // All the data is zero. |
| 44 return false; |
| 45 } |
| 46 |
| 33 } // namespace | 47 } // namespace |
| 34 | 48 |
| 35 // Reference counted container of WebRtcLocalAudioTrack delegate. | 49 // Reference counted container of WebRtcLocalAudioTrack delegate. |
| 36 // TODO(xians): Switch to MediaStreamAudioSinkOwner. | 50 // TODO(xians): Switch to MediaStreamAudioSinkOwner. |
| 37 class WebRtcAudioCapturer::TrackOwner | 51 class WebRtcAudioCapturer::TrackOwner |
| 38 : public base::RefCountedThreadSafe<WebRtcAudioCapturer::TrackOwner> { | 52 : public base::RefCountedThreadSafe<WebRtcAudioCapturer::TrackOwner> { |
| 39 public: | 53 public: |
| 40 explicit TrackOwner(WebRtcLocalAudioTrack* track) | 54 explicit TrackOwner(WebRtcLocalAudioTrack* track) |
| 41 : delegate_(track) {} | 55 : delegate_(track) {} |
| 42 | 56 |
| 43 void Capture(const int16* audio_data, | 57 void Capture(const int16* audio_data, |
| 44 base::TimeDelta delay, | 58 base::TimeDelta delay, |
| 45 double volume, | 59 double volume, |
| 46 bool key_pressed, | 60 bool key_pressed, |
| 47 bool need_audio_processing) { | 61 bool need_audio_processing, |
| 62 bool force_report_nonzero_energy) { |
| 48 base::AutoLock lock(lock_); | 63 base::AutoLock lock(lock_); |
| 49 if (delegate_) { | 64 if (delegate_) { |
| 50 delegate_->Capture(audio_data, | 65 delegate_->Capture(audio_data, |
| 51 delay, | 66 delay, |
| 52 volume, | 67 volume, |
| 53 key_pressed, | 68 key_pressed, |
| 54 need_audio_processing); | 69 need_audio_processing, |
| 70 force_report_nonzero_energy); |
| 55 } | 71 } |
| 56 } | 72 } |
| 57 | 73 |
| 58 void OnSetFormat(const media::AudioParameters& params) { | 74 void OnSetFormat(const media::AudioParameters& params) { |
| 59 base::AutoLock lock(lock_); | 75 base::AutoLock lock(lock_); |
| 60 if (delegate_) | 76 if (delegate_) |
| 61 delegate_->OnSetFormat(params); | 77 delegate_->OnSetFormat(params); |
| 62 } | 78 } |
| 63 | 79 |
| 64 void SetAudioProcessor( | 80 void SetAudioProcessor( |
| (...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 507 last_audio_level_log_time_ = base::TimeTicks::Now(); | 523 last_audio_level_log_time_ = base::TimeTicks::Now(); |
| 508 | 524 |
| 509 std::pair<float, bool> result = | 525 std::pair<float, bool> result = |
| 510 audio_power_monitor_.ReadCurrentPowerAndClip(); | 526 audio_power_monitor_.ReadCurrentPowerAndClip(); |
| 511 WebRtcLogMessage(base::StringPrintf( | 527 WebRtcLogMessage(base::StringPrintf( |
| 512 "WAC::Capture: current_audio_power=%.2fdBFS.", result.first)); | 528 "WAC::Capture: current_audio_power=%.2fdBFS.", result.first)); |
| 513 | 529 |
| 514 audio_power_monitor_.Reset(); | 530 audio_power_monitor_.Reset(); |
| 515 } | 531 } |
| 516 | 532 |
| 533 // Figure out if the pre-processed data has any energy or not, the |
| 534 // information will be passed to the track to force the calculator |
| 535 // to report energy in case the post-processed data is zeroed by the audio |
| 536 // processing. |
| 537 const bool force_report_nonzero_energy = HasDataEnergy(*audio_source); |
| 538 |
| 517 // Push the data to the processor for processing. | 539 // Push the data to the processor for processing. |
| 518 audio_processor_->PushCaptureData(audio_source); | 540 audio_processor_->PushCaptureData(audio_source); |
| 519 | 541 |
| 520 // Process and consume the data in the processor until there is not enough | 542 // Process and consume the data in the processor until there is not enough |
| 521 // data in the processor. | 543 // data in the processor. |
| 522 int16* output = NULL; | 544 int16* output = NULL; |
| 523 int new_volume = 0; | 545 int new_volume = 0; |
| 524 while (audio_processor_->ProcessAndConsumeData( | 546 while (audio_processor_->ProcessAndConsumeData( |
| 525 audio_delay, current_volume, key_pressed, &new_volume, &output)) { | 547 audio_delay, current_volume, key_pressed, &new_volume, &output)) { |
| 526 // Feed the post-processed data to the tracks. | 548 // Feed the post-processed data to the tracks. |
| 527 for (TrackList::ItemList::const_iterator it = tracks.begin(); | 549 for (TrackList::ItemList::const_iterator it = tracks.begin(); |
| 528 it != tracks.end(); ++it) { | 550 it != tracks.end(); ++it) { |
| 529 (*it)->Capture(output, audio_delay, current_volume, key_pressed, | 551 (*it)->Capture(output, audio_delay, current_volume, key_pressed, |
| 530 need_audio_processing); | 552 need_audio_processing, force_report_nonzero_energy); |
| 531 } | 553 } |
| 532 | 554 |
| 533 if (new_volume) { | 555 if (new_volume) { |
| 534 SetVolume(new_volume); | 556 SetVolume(new_volume); |
| 535 | 557 |
| 536 // Update the |current_volume| to avoid passing the old volume to AGC. | 558 // Update the |current_volume| to avoid passing the old volume to AGC. |
| 537 current_volume = new_volume; | 559 current_volume = new_volume; |
| 538 } | 560 } |
| 539 } | 561 } |
| 540 } | 562 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 600 | 622 |
| 601 void WebRtcAudioCapturer::SetCapturerSourceForTesting( | 623 void WebRtcAudioCapturer::SetCapturerSourceForTesting( |
| 602 const scoped_refptr<media::AudioCapturerSource>& source, | 624 const scoped_refptr<media::AudioCapturerSource>& source, |
| 603 media::AudioParameters params) { | 625 media::AudioParameters params) { |
| 604 // Create a new audio stream as source which uses the new source. | 626 // Create a new audio stream as source which uses the new source. |
| 605 SetCapturerSource(source, params.channel_layout(), | 627 SetCapturerSource(source, params.channel_layout(), |
| 606 static_cast<float>(params.sample_rate())); | 628 static_cast<float>(params.sample_rate())); |
| 607 } | 629 } |
| 608 | 630 |
| 609 } // namespace content | 631 } // namespace content |
| OLD | NEW |