tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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