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 |