Move dynamic memory allocations of webrtc::AudioMixerImpl from RT thead

(4 vector allocations removed)

Bug: webrtc:12035,webrtc:12036
Change-Id: Ie0d734cd0016a27c57809af67187ceb97f92f233
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/188621
Commit-Queue: Olga Sharonova <olka@webrtc.org>
Reviewed-by: Alessio Bazzica <alessiob@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Per Ã…hgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32441}
diff --git a/modules/audio_mixer/audio_mixer_impl.cc b/modules/audio_mixer/audio_mixer_impl.cc
index 6552953..04a8bcf 100644
--- a/modules/audio_mixer/audio_mixer_impl.cc
+++ b/modules/audio_mixer/audio_mixer_impl.cc
@@ -24,9 +24,23 @@
 #include "rtc_base/ref_counted_object.h"
 
 namespace webrtc {
+
+struct AudioMixerImpl::SourceStatus {
+  SourceStatus(Source* audio_source, bool is_mixed, float gain)
+      : audio_source(audio_source), is_mixed(is_mixed), gain(gain) {}
+  Source* audio_source = nullptr;
+  bool is_mixed = false;
+  float gain = 0.0f;
+
+  // A frame that will be passed to audio_source->GetAudioFrameWithInfo.
+  AudioFrame audio_frame;
+};
+
 namespace {
 
 struct SourceFrame {
+  SourceFrame() = default;
+
   SourceFrame(AudioMixerImpl::SourceStatus* source_status,
               AudioFrame* audio_frame,
               bool muted)
@@ -57,6 +71,7 @@
 };
 
 // ShouldMixBefore(a, b) is used to select mixer sources.
+// Returns true if `a` is preferred over `b` as a source to be mixed.
 bool ShouldMixBefore(const SourceFrame& a, const SourceFrame& b) {
   if (a.muted != b.muted) {
     return b.muted;
@@ -73,7 +88,7 @@
 }
 
 void RampAndUpdateGain(
-    const std::vector<SourceFrame>& mixed_sources_and_frames) {
+    rtc::ArrayView<const SourceFrame> mixed_sources_and_frames) {
   for (const auto& source_frame : mixed_sources_and_frames) {
     float target_gain = source_frame.source_status->is_mixed ? 1.0f : 0.0f;
     Ramp(source_frame.source_status->gain, target_gain,
@@ -82,9 +97,11 @@
   }
 }
 
-AudioMixerImpl::SourceStatusList::const_iterator FindSourceInList(
+std::vector<std::unique_ptr<AudioMixerImpl::SourceStatus>>::const_iterator
+FindSourceInList(
     AudioMixerImpl::Source const* audio_source,
-    AudioMixerImpl::SourceStatusList const* audio_source_list) {
+    std::vector<std::unique_ptr<AudioMixerImpl::SourceStatus>> const*
+        audio_source_list) {
   return std::find_if(
       audio_source_list->begin(), audio_source_list->end(),
       [audio_source](const std::unique_ptr<AudioMixerImpl::SourceStatus>& p) {
@@ -93,14 +110,31 @@
 }
 }  // namespace
 
+struct AudioMixerImpl::HelperContainers {
+  void resize(size_t size) {
+    audio_to_mix.resize(size);
+    audio_source_mixing_data_list.resize(size);
+    ramp_list.resize(size);
+    preferred_rates.resize(size);
+  }
+
+  std::vector<AudioFrame*> audio_to_mix;
+  std::vector<SourceFrame> audio_source_mixing_data_list;
+  std::vector<SourceFrame> ramp_list;
+  std::vector<int> preferred_rates;
+};
+
 AudioMixerImpl::AudioMixerImpl(
     std::unique_ptr<OutputRateCalculator> output_rate_calculator,
     bool use_limiter)
     : output_rate_calculator_(std::move(output_rate_calculator)),
-      output_frequency_(0),
-      sample_size_(0),
       audio_source_list_(),
-      frame_combiner_(use_limiter) {}
+      helper_containers_(std::make_unique<HelperContainers>()),
+      frame_combiner_(use_limiter) {
+  const int kTypicalMaxNumberOfMixedStreams = 3;
+  audio_source_list_.reserve(kTypicalMaxNumberOfMixedStreams);
+  helper_containers_->resize(kTypicalMaxNumberOfMixedStreams);
+}
 
 AudioMixerImpl::~AudioMixerImpl() {}
 
@@ -121,40 +155,23 @@
 void AudioMixerImpl::Mix(size_t number_of_channels,
                          AudioFrame* audio_frame_for_mixing) {
   RTC_DCHECK(number_of_channels >= 1);
-  RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);
-
-  CalculateOutputFrequency();
-
-  {
-    MutexLock lock(&mutex_);
-    const size_t number_of_streams = audio_source_list_.size();
-    frame_combiner_.Combine(GetAudioFromSources(), number_of_channels,
-                            OutputFrequency(), number_of_streams,
-                            audio_frame_for_mixing);
-  }
-
-  return;
-}
-
-void AudioMixerImpl::CalculateOutputFrequency() {
-  RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);
   MutexLock lock(&mutex_);
 
-  std::vector<int> preferred_rates;
+  size_t number_of_streams = audio_source_list_.size();
+
   std::transform(audio_source_list_.begin(), audio_source_list_.end(),
-                 std::back_inserter(preferred_rates),
+                 helper_containers_->preferred_rates.begin(),
                  [&](std::unique_ptr<SourceStatus>& a) {
                    return a->audio_source->PreferredSampleRate();
                  });
 
-  output_frequency_ =
-      output_rate_calculator_->CalculateOutputRate(preferred_rates);
-  sample_size_ = (output_frequency_ * kFrameDurationInMs) / 1000;
-}
+  int output_frequency = output_rate_calculator_->CalculateOutputRateFromRange(
+      rtc::ArrayView<const int>(helper_containers_->preferred_rates.data(),
+                                number_of_streams));
 
-int AudioMixerImpl::OutputFrequency() const {
-  RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);
-  return output_frequency_;
+  frame_combiner_.Combine(GetAudioFromSources(output_frequency),
+                          number_of_channels, output_frequency,
+                          number_of_streams, audio_frame_for_mixing);
 }
 
 bool AudioMixerImpl::AddSource(Source* audio_source) {
@@ -164,6 +181,7 @@
              audio_source_list_.end())
       << "Source already added to mixer";
   audio_source_list_.emplace_back(new SourceStatus(audio_source, false, 0));
+  helper_containers_->resize(audio_source_list_.size());
   return true;
 }
 
@@ -175,35 +193,37 @@
   audio_source_list_.erase(iter);
 }
 
-AudioFrameList AudioMixerImpl::GetAudioFromSources() {
-  RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);
-  AudioFrameList result;
-  std::vector<SourceFrame> audio_source_mixing_data_list;
-  std::vector<SourceFrame> ramp_list;
-
+rtc::ArrayView<AudioFrame* const> AudioMixerImpl::GetAudioFromSources(
+    int output_frequency) {
   // Get audio from the audio sources and put it in the SourceFrame vector.
+  int audio_source_mixing_data_count = 0;
   for (auto& source_and_status : audio_source_list_) {
     const auto audio_frame_info =
         source_and_status->audio_source->GetAudioFrameWithInfo(
-            OutputFrequency(), &source_and_status->audio_frame);
+            output_frequency, &source_and_status->audio_frame);
 
     if (audio_frame_info == Source::AudioFrameInfo::kError) {
       RTC_LOG_F(LS_WARNING) << "failed to GetAudioFrameWithInfo() from source";
       continue;
     }
-    audio_source_mixing_data_list.emplace_back(
-        source_and_status.get(), &source_and_status->audio_frame,
-        audio_frame_info == Source::AudioFrameInfo::kMuted);
+    helper_containers_
+        ->audio_source_mixing_data_list[audio_source_mixing_data_count++] =
+        SourceFrame(source_and_status.get(), &source_and_status->audio_frame,
+                    audio_frame_info == Source::AudioFrameInfo::kMuted);
   }
+  rtc::ArrayView<SourceFrame> audio_source_mixing_data_view(
+      helper_containers_->audio_source_mixing_data_list.data(),
+      audio_source_mixing_data_count);
 
   // Sort frames by sorting function.
-  std::sort(audio_source_mixing_data_list.begin(),
-            audio_source_mixing_data_list.end(), ShouldMixBefore);
+  std::sort(audio_source_mixing_data_view.begin(),
+            audio_source_mixing_data_view.end(), ShouldMixBefore);
 
   int max_audio_frame_counter = kMaximumAmountOfMixedAudioSources;
-
+  int ramp_list_lengh = 0;
+  int audio_to_mix_count = 0;
   // Go through list in order and put unmuted frames in result list.
-  for (const auto& p : audio_source_mixing_data_list) {
+  for (const auto& p : audio_source_mixing_data_view) {
     // Filter muted.
     if (p.muted) {
       p.source_status->is_mixed = false;
@@ -214,19 +234,21 @@
     bool is_mixed = false;
     if (max_audio_frame_counter > 0) {
       --max_audio_frame_counter;
-      result.push_back(p.audio_frame);
-      ramp_list.emplace_back(p.source_status, p.audio_frame, false, -1);
+      helper_containers_->audio_to_mix[audio_to_mix_count++] = p.audio_frame;
+      helper_containers_->ramp_list[ramp_list_lengh++] =
+          SourceFrame(p.source_status, p.audio_frame, false, -1);
       is_mixed = true;
     }
     p.source_status->is_mixed = is_mixed;
   }
-  RampAndUpdateGain(ramp_list);
-  return result;
+  RampAndUpdateGain(rtc::ArrayView<SourceFrame>(
+      helper_containers_->ramp_list.data(), ramp_list_lengh));
+  return rtc::ArrayView<AudioFrame* const>(
+      helper_containers_->audio_to_mix.data(), audio_to_mix_count);
 }
 
 bool AudioMixerImpl::GetAudioSourceMixabilityStatusForTest(
     AudioMixerImpl::Source* audio_source) const {
-  RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);
   MutexLock lock(&mutex_);
 
   const auto iter = FindSourceInList(audio_source, &audio_source_list_);
diff --git a/modules/audio_mixer/audio_mixer_impl.h b/modules/audio_mixer/audio_mixer_impl.h
index 57b1f5e..0a13082 100644
--- a/modules/audio_mixer/audio_mixer_impl.h
+++ b/modules/audio_mixer/audio_mixer_impl.h
@@ -16,6 +16,7 @@
 #include <memory>
 #include <vector>
 
+#include "api/array_view.h"
 #include "api/audio/audio_frame.h"
 #include "api/audio/audio_mixer.h"
 #include "api/scoped_refptr.h"
@@ -28,22 +29,9 @@
 
 namespace webrtc {
 
-typedef std::vector<AudioFrame*> AudioFrameList;
-
 class AudioMixerImpl : public AudioMixer {
  public:
-  struct SourceStatus {
-    SourceStatus(Source* audio_source, bool is_mixed, float gain)
-        : audio_source(audio_source), is_mixed(is_mixed), gain(gain) {}
-    Source* audio_source = nullptr;
-    bool is_mixed = false;
-    float gain = 0.0f;
-
-    // A frame that will be passed to audio_source->GetAudioFrameWithInfo.
-    AudioFrame audio_frame;
-  };
-
-  using SourceStatusList = std::vector<std::unique_ptr<SourceStatus>>;
+  struct SourceStatus;
 
   // AudioProcessing only accepts 10 ms frames.
   static const int kFrameDurationInMs = 10;
@@ -75,32 +63,29 @@
                  bool use_limiter);
 
  private:
-  // Set mixing frequency through OutputFrequencyCalculator.
-  void CalculateOutputFrequency();
-  // Get mixing frequency.
-  int OutputFrequency() const;
+  struct HelperContainers;
 
   // Compute what audio sources to mix from audio_source_list_. Ramp
   // in and out. Update mixed status. Mixes up to
   // kMaximumAmountOfMixedAudioSources audio sources.
-  AudioFrameList GetAudioFromSources() RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+  rtc::ArrayView<AudioFrame* const> GetAudioFromSources(int output_frequency)
+      RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
 
   // The critical section lock guards audio source insertion and
   // removal, which can be done from any thread. The race checker
   // checks that mixing is done sequentially.
   mutable Mutex mutex_;
-  rtc::RaceChecker race_checker_;
 
   std::unique_ptr<OutputRateCalculator> output_rate_calculator_;
-  // The current sample frequency and sample size when mixing.
-  int output_frequency_ RTC_GUARDED_BY(race_checker_);
-  size_t sample_size_ RTC_GUARDED_BY(race_checker_);
 
-  // List of all audio sources. Note all lists are disjunct
-  SourceStatusList audio_source_list_ RTC_GUARDED_BY(mutex_);  // May be mixed.
+  // List of all audio sources.
+  std::vector<std::unique_ptr<SourceStatus>> audio_source_list_
+      RTC_GUARDED_BY(mutex_);
+  const std::unique_ptr<HelperContainers> helper_containers_
+      RTC_GUARDED_BY(mutex_);
 
   // Component that handles actual adding of audio frames.
-  FrameCombiner frame_combiner_ RTC_GUARDED_BY(race_checker_);
+  FrameCombiner frame_combiner_;
 
   RTC_DISALLOW_COPY_AND_ASSIGN(AudioMixerImpl);
 };
diff --git a/modules/audio_mixer/audio_mixer_impl_unittest.cc b/modules/audio_mixer/audio_mixer_impl_unittest.cc
index 383771c..18a4384 100644
--- a/modules/audio_mixer/audio_mixer_impl_unittest.cc
+++ b/modules/audio_mixer/audio_mixer_impl_unittest.cc
@@ -105,7 +105,8 @@
 class CustomRateCalculator : public OutputRateCalculator {
  public:
   explicit CustomRateCalculator(int rate) : rate_(rate) {}
-  int CalculateOutputRate(const std::vector<int>& preferred_rates) override {
+  int CalculateOutputRateFromRange(
+      rtc::ArrayView<const int> preferred_rates) override {
     return rate_;
   }
 
@@ -598,8 +599,8 @@
 class HighOutputRateCalculator : public OutputRateCalculator {
  public:
   static const int kDefaultFrequency = 76000;
-  int CalculateOutputRate(
-      const std::vector<int>& preferred_sample_rates) override {
+  int CalculateOutputRateFromRange(
+      rtc::ArrayView<const int> preferred_sample_rates) override {
     return kDefaultFrequency;
   }
   ~HighOutputRateCalculator() override {}
diff --git a/modules/audio_mixer/default_output_rate_calculator.cc b/modules/audio_mixer/default_output_rate_calculator.cc
index 57d88b6..5f24b65 100644
--- a/modules/audio_mixer/default_output_rate_calculator.cc
+++ b/modules/audio_mixer/default_output_rate_calculator.cc
@@ -18,14 +18,14 @@
 
 namespace webrtc {
 
-int DefaultOutputRateCalculator::CalculateOutputRate(
-    const std::vector<int>& preferred_sample_rates) {
+int DefaultOutputRateCalculator::CalculateOutputRateFromRange(
+    rtc::ArrayView<const int> preferred_sample_rates) {
   if (preferred_sample_rates.empty()) {
     return DefaultOutputRateCalculator::kDefaultFrequency;
   }
   using NativeRate = AudioProcessing::NativeRate;
   const int maximal_frequency = *std::max_element(
-      preferred_sample_rates.begin(), preferred_sample_rates.end());
+      preferred_sample_rates.cbegin(), preferred_sample_rates.cend());
 
   RTC_DCHECK_LE(NativeRate::kSampleRate8kHz, maximal_frequency);
   RTC_DCHECK_GE(NativeRate::kSampleRate48kHz, maximal_frequency);
diff --git a/modules/audio_mixer/default_output_rate_calculator.h b/modules/audio_mixer/default_output_rate_calculator.h
index 2d34f34..a7aaf68 100644
--- a/modules/audio_mixer/default_output_rate_calculator.h
+++ b/modules/audio_mixer/default_output_rate_calculator.h
@@ -13,6 +13,7 @@
 
 #include <vector>
 
+#include "api/array_view.h"
 #include "modules/audio_mixer/output_rate_calculator.h"
 
 namespace webrtc {
@@ -25,8 +26,8 @@
   // sample rates. A native rate is one in
   // AudioProcessing::NativeRate. If |preferred_sample_rates| is
   // empty, returns |kDefaultFrequency|.
-  int CalculateOutputRate(
-      const std::vector<int>& preferred_sample_rates) override;
+  int CalculateOutputRateFromRange(
+      rtc::ArrayView<const int> preferred_sample_rates) override;
   ~DefaultOutputRateCalculator() override {}
 };
 
diff --git a/modules/audio_mixer/frame_combiner.cc b/modules/audio_mixer/frame_combiner.cc
index f7c6a0c..e184506 100644
--- a/modules/audio_mixer/frame_combiner.cc
+++ b/modules/audio_mixer/frame_combiner.cc
@@ -35,7 +35,7 @@
     std::array<std::array<float, FrameCombiner::kMaximumChannelSize>,
                FrameCombiner::kMaximumNumberOfChannels>;
 
-void SetAudioFrameFields(const std::vector<AudioFrame*>& mix_list,
+void SetAudioFrameFields(rtc::ArrayView<const AudioFrame* const> mix_list,
                          size_t number_of_channels,
                          int sample_rate,
                          size_t number_of_streams,
@@ -61,7 +61,7 @@
   }
 }
 
-void MixFewFramesWithNoLimiter(const std::vector<AudioFrame*>& mix_list,
+void MixFewFramesWithNoLimiter(rtc::ArrayView<const AudioFrame* const> mix_list,
                                AudioFrame* audio_frame_for_mixing) {
   if (mix_list.empty()) {
     audio_frame_for_mixing->Mute();
@@ -74,7 +74,7 @@
             audio_frame_for_mixing->mutable_data());
 }
 
-void MixToFloatFrame(const std::vector<AudioFrame*>& mix_list,
+void MixToFloatFrame(rtc::ArrayView<const AudioFrame* const> mix_list,
                      size_t samples_per_channel,
                      size_t number_of_channels,
                      MixingBuffer* mixing_buffer) {
@@ -140,7 +140,7 @@
 
 FrameCombiner::~FrameCombiner() = default;
 
-void FrameCombiner::Combine(const std::vector<AudioFrame*>& mix_list,
+void FrameCombiner::Combine(rtc::ArrayView<AudioFrame* const> mix_list,
                             size_t number_of_channels,
                             int sample_rate,
                             size_t number_of_streams,
@@ -195,9 +195,10 @@
   InterleaveToAudioFrame(mixing_buffer_view, audio_frame_for_mixing);
 }
 
-void FrameCombiner::LogMixingStats(const std::vector<AudioFrame*>& mix_list,
-                                   int sample_rate,
-                                   size_t number_of_streams) const {
+void FrameCombiner::LogMixingStats(
+    rtc::ArrayView<const AudioFrame* const> mix_list,
+    int sample_rate,
+    size_t number_of_streams) const {
   // Log every second.
   uma_logging_counter_++;
   if (uma_logging_counter_ > 1000 / AudioMixerImpl::kFrameDurationInMs) {
diff --git a/modules/audio_mixer/frame_combiner.h b/modules/audio_mixer/frame_combiner.h
index d989d02..9ddf81e 100644
--- a/modules/audio_mixer/frame_combiner.h
+++ b/modules/audio_mixer/frame_combiner.h
@@ -14,6 +14,7 @@
 #include <memory>
 #include <vector>
 
+#include "api/array_view.h"
 #include "api/audio/audio_frame.h"
 #include "modules/audio_processing/agc2/limiter.h"
 
@@ -32,7 +33,7 @@
   // because 'mix_list' can be empty. The parameter
   // 'number_of_streams' is used for determining whether to pass the
   // data through a limiter.
-  void Combine(const std::vector<AudioFrame*>& mix_list,
+  void Combine(rtc::ArrayView<AudioFrame* const> mix_list,
                size_t number_of_channels,
                int sample_rate,
                size_t number_of_streams,
@@ -46,7 +47,7 @@
                                   kMaximumNumberOfChannels>;
 
  private:
-  void LogMixingStats(const std::vector<AudioFrame*>& mix_list,
+  void LogMixingStats(rtc::ArrayView<const AudioFrame* const> mix_list,
                       int sample_rate,
                       size_t number_of_streams) const;
 
diff --git a/modules/audio_mixer/output_rate_calculator.h b/modules/audio_mixer/output_rate_calculator.h
index cb3ca96..d32fb29 100644
--- a/modules/audio_mixer/output_rate_calculator.h
+++ b/modules/audio_mixer/output_rate_calculator.h
@@ -13,14 +13,29 @@
 
 #include <vector>
 
+#include "api/array_view.h"
+
 namespace webrtc {
 
 // Decides the sample rate of a mixing iteration given the preferred
 // sample rates of the sources.
 class OutputRateCalculator {
  public:
+  virtual int CalculateOutputRateFromRange(
+      rtc::ArrayView<const int> preferred_sample_rates) {
+    // TODO(olka): Temporary workaround to reslove client dependencies.
+    std::vector<int> sample_rates(preferred_sample_rates.cbegin(),
+                                  preferred_sample_rates.cend());
+    return CalculateOutputRate(sample_rates);
+  }
+
+  // TODO(olka) to be removed as soon as the clients are switched to
+  // CalculateOutputRateFromRange()
   virtual int CalculateOutputRate(
-      const std::vector<int>& preferred_sample_rates) = 0;
+      const std::vector<int>& preferred_sample_rates) {
+    return CalculateOutputRateFromRange(preferred_sample_rates);
+  }
+
   virtual ~OutputRateCalculator() {}
 };