audio_mixer_impl.cc (5886B)
1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "modules/audio_mixer/audio_mixer_impl.h" 12 13 #include <algorithm> 14 #include <cstddef> 15 #include <memory> 16 #include <utility> 17 #include <vector> 18 19 #include "api/array_view.h" 20 #include "api/audio/audio_frame.h" 21 #include "api/make_ref_counted.h" 22 #include "api/scoped_refptr.h" 23 #include "modules/audio_mixer/default_output_rate_calculator.h" 24 #include "modules/audio_mixer/output_rate_calculator.h" 25 #include "rtc_base/checks.h" 26 #include "rtc_base/logging.h" 27 #include "rtc_base/synchronization/mutex.h" 28 #include "rtc_base/trace_event.h" 29 #include "system_wrappers/include/metrics.h" 30 31 namespace webrtc { 32 33 struct AudioMixerImpl::SourceStatus { 34 explicit SourceStatus(Source* audio_source) : audio_source(audio_source) {} 35 Source* audio_source = nullptr; 36 37 // A frame that will be passed to audio_source->GetAudioFrameWithInfo. 38 AudioFrame audio_frame; 39 }; 40 41 namespace { 42 43 std::vector<std::unique_ptr<AudioMixerImpl::SourceStatus>>::const_iterator 44 FindSourceInList( 45 AudioMixerImpl::Source const* audio_source, 46 std::vector<std::unique_ptr<AudioMixerImpl::SourceStatus>> const* 47 audio_source_list) { 48 return std::find_if( 49 audio_source_list->begin(), audio_source_list->end(), 50 [audio_source](const std::unique_ptr<AudioMixerImpl::SourceStatus>& p) { 51 return p->audio_source == audio_source; 52 }); 53 } 54 } // namespace 55 56 struct AudioMixerImpl::HelperContainers { 57 void resize(size_t size) { 58 audio_to_mix.resize(size); 59 preferred_rates.resize(size); 60 } 61 62 std::vector<AudioFrame*> audio_to_mix; 63 std::vector<int> preferred_rates; 64 }; 65 66 AudioMixerImpl::AudioMixerImpl( 67 std::unique_ptr<OutputRateCalculator> output_rate_calculator, 68 bool use_limiter) 69 : output_rate_calculator_(std::move(output_rate_calculator)), 70 audio_source_list_(), 71 helper_containers_(std::make_unique<HelperContainers>()), 72 frame_combiner_(use_limiter) {} 73 74 AudioMixerImpl::~AudioMixerImpl() {} 75 76 scoped_refptr<AudioMixerImpl> AudioMixerImpl::Create() { 77 return Create(std::unique_ptr<DefaultOutputRateCalculator>( 78 new DefaultOutputRateCalculator()), 79 /*use_limiter=*/true); 80 } 81 82 scoped_refptr<AudioMixerImpl> AudioMixerImpl::Create( 83 std::unique_ptr<OutputRateCalculator> output_rate_calculator, 84 bool use_limiter) { 85 return make_ref_counted<AudioMixerImpl>(std::move(output_rate_calculator), 86 use_limiter); 87 } 88 89 void AudioMixerImpl::Mix(size_t number_of_channels, 90 AudioFrame* audio_frame_for_mixing) { 91 TRACE_EVENT0("webrtc", "AudioMixerImpl::Mix"); 92 RTC_DCHECK(number_of_channels >= 1); 93 MutexLock lock(&mutex_); 94 95 size_t number_of_streams = audio_source_list_.size(); 96 97 std::transform(audio_source_list_.begin(), audio_source_list_.end(), 98 helper_containers_->preferred_rates.begin(), 99 [&](std::unique_ptr<SourceStatus>& a) { 100 return a->audio_source->PreferredSampleRate(); 101 }); 102 103 int output_frequency = output_rate_calculator_->CalculateOutputRateFromRange( 104 ArrayView<const int>(helper_containers_->preferred_rates.data(), 105 number_of_streams)); 106 107 frame_combiner_.Combine(GetAudioFromSources(output_frequency), 108 number_of_channels, output_frequency, 109 number_of_streams, audio_frame_for_mixing); 110 } 111 112 bool AudioMixerImpl::AddSource(Source* audio_source) { 113 RTC_DCHECK(audio_source); 114 MutexLock lock(&mutex_); 115 RTC_DCHECK(FindSourceInList(audio_source, &audio_source_list_) == 116 audio_source_list_.end()) 117 << "Source already added to mixer"; 118 audio_source_list_.emplace_back(new SourceStatus(audio_source)); 119 helper_containers_->resize(audio_source_list_.size()); 120 UpdateSourceCountStats(); 121 return true; 122 } 123 124 void AudioMixerImpl::RemoveSource(Source* audio_source) { 125 RTC_DCHECK(audio_source); 126 MutexLock lock(&mutex_); 127 const auto iter = FindSourceInList(audio_source, &audio_source_list_); 128 RTC_DCHECK(iter != audio_source_list_.end()) << "Source not present in mixer"; 129 audio_source_list_.erase(iter); 130 } 131 132 ArrayView<AudioFrame* const> AudioMixerImpl::GetAudioFromSources( 133 int output_frequency) { 134 int audio_to_mix_count = 0; 135 for (auto& source_and_status : audio_source_list_) { 136 const auto audio_frame_info = 137 source_and_status->audio_source->GetAudioFrameWithInfo( 138 output_frequency, &source_and_status->audio_frame); 139 switch (audio_frame_info) { 140 case Source::AudioFrameInfo::kError: 141 RTC_LOG_F(LS_WARNING) 142 << "failed to GetAudioFrameWithInfo() from source"; 143 break; 144 case Source::AudioFrameInfo::kMuted: 145 break; 146 case Source::AudioFrameInfo::kNormal: 147 helper_containers_->audio_to_mix[audio_to_mix_count++] = 148 &source_and_status->audio_frame; 149 } 150 } 151 return ArrayView<AudioFrame* const>(helper_containers_->audio_to_mix.data(), 152 audio_to_mix_count); 153 } 154 155 void AudioMixerImpl::UpdateSourceCountStats() { 156 size_t current_source_count = audio_source_list_.size(); 157 // Log to the histogram whenever the maximum number of sources increases. 158 if (current_source_count > max_source_count_ever_) { 159 RTC_HISTOGRAM_COUNTS_LINEAR("WebRTC.Audio.AudioMixer.NewHighestSourceCount", 160 current_source_count, 1, 20, 20); 161 max_source_count_ever_ = current_source_count; 162 } 163 } 164 } // namespace webrtc