| Index: webrtc/modules/audio_mixer/audio_mixer_impl.cc
 | 
| diff --git a/webrtc/modules/audio_mixer/audio_mixer_impl.cc b/webrtc/modules/audio_mixer/audio_mixer_impl.cc
 | 
| index 93b78bd4c34947ec91a514097384e4644e0a6402..ee78eef2a13a9767b0d47651834c24a7eb0a9660 100644
 | 
| --- a/webrtc/modules/audio_mixer/audio_mixer_impl.cc
 | 
| +++ b/webrtc/modules/audio_mixer/audio_mixer_impl.cc
 | 
| @@ -37,6 +37,17 @@ class SourceFrame {
 | 
|      }
 | 
|    }
 | 
|  
 | 
| +  SourceFrame(MixerAudioSource* p,
 | 
| +              AudioFrame* a,
 | 
| +              bool m,
 | 
| +              bool was_mixed_before,
 | 
| +              uint32_t energy)
 | 
| +      : audio_source_(p),
 | 
| +        audio_frame_(a),
 | 
| +        muted_(m),
 | 
| +        energy_(energy),
 | 
| +        was_mixed_before_(was_mixed_before) {}
 | 
| +
 | 
|    // a.shouldMixBefore(b) is used to select mixer participants.
 | 
|    bool shouldMixBefore(const SourceFrame& other) const {
 | 
|      if (muted_ != other.muted_) {
 | 
| @@ -70,20 +81,19 @@ void RemixFrame(AudioFrame* frame, size_t number_of_channels) {
 | 
|    }
 | 
|  }
 | 
|  
 | 
| -// Mix |frame| into |mixed_frame|, with saturation protection and upmixing.
 | 
| -// These effects are applied to |frame| itself prior to mixing. Assumes that
 | 
| -// |mixed_frame| always has at least as many channels as |frame|. Supports
 | 
| -// stereo at most.
 | 
| -//
 | 
| -void MixFrames(AudioFrame* mixed_frame, AudioFrame* frame, bool use_limiter) {
 | 
| -  RTC_DCHECK_GE(mixed_frame->num_channels_, frame->num_channels_);
 | 
| -  if (use_limiter) {
 | 
| -    // Divide by two to avoid saturation in the mixing.
 | 
| -    // This is only meaningful if the limiter will be used.
 | 
| -    *frame >>= 1;
 | 
| +void Ramp(const std::vector<SourceFrame>& mixed_sources_and_frames) {
 | 
| +  for (const auto& source_frame : mixed_sources_and_frames) {
 | 
| +    // Ramp in previously unmixed.
 | 
| +    if (!source_frame.was_mixed_before_) {
 | 
| +      NewMixerRampIn(source_frame.audio_frame_);
 | 
| +    }
 | 
| +
 | 
| +    const bool is_mixed = source_frame.audio_source_->_mixHistory->IsMixed();
 | 
| +    // Ramp out currently unmixed.
 | 
| +    if (source_frame.was_mixed_before_ && !is_mixed) {
 | 
| +      NewMixerRampOut(source_frame.audio_frame_);
 | 
| +    }
 | 
|    }
 | 
| -  RTC_DCHECK_EQ(frame->num_channels_, mixed_frame->num_channels_);
 | 
| -  *mixed_frame += *frame;
 | 
|  }
 | 
|  
 | 
|  }  // namespace
 | 
| @@ -188,21 +198,21 @@ void AudioMixerImpl::Mix(int sample_rate,
 | 
|      SetOutputFrequency(static_cast<Frequency>(sample_rate));
 | 
|    }
 | 
|  
 | 
| -  AudioFrameList mixList;
 | 
| -  AudioFrameList additionalFramesList;
 | 
| +  AudioFrameList mix_list;
 | 
| +  AudioFrameList anonymous_mix_list;
 | 
|    int num_mixed_audio_sources;
 | 
|    {
 | 
|      rtc::CritScope lock(&crit_);
 | 
| -    mixList = UpdateToMix(kMaximumAmountOfMixedAudioSources);
 | 
| -    GetAdditionalAudio(&additionalFramesList);
 | 
| +    mix_list = GetNonAnonymousAudio();
 | 
| +    anonymous_mix_list = GetAnonymousAudio();
 | 
|      num_mixed_audio_sources = static_cast<int>(num_mixed_audio_sources_);
 | 
|    }
 | 
|  
 | 
| -  for (FrameAndMuteInfo& frame_and_mute : mixList) {
 | 
| -    RemixFrame(frame_and_mute.frame, number_of_channels);
 | 
| -  }
 | 
| -  for (FrameAndMuteInfo& frame_and_mute : additionalFramesList) {
 | 
| -    RemixFrame(frame_and_mute.frame, number_of_channels);
 | 
| +  mix_list.insert(mix_list.begin(), anonymous_mix_list.begin(),
 | 
| +                  anonymous_mix_list.end());
 | 
| +
 | 
| +  for (const auto& frame : mix_list) {
 | 
| +    RemixFrame(frame, number_of_channels);
 | 
|    }
 | 
|  
 | 
|    audio_frame_for_mixing->UpdateFrame(
 | 
| @@ -213,10 +223,9 @@ void AudioMixerImpl::Mix(int sample_rate,
 | 
|  
 | 
|    use_limiter_ = num_mixed_audio_sources > 1;
 | 
|  
 | 
| -  // We only use the limiter if it supports the output sample rate and
 | 
| -  // we're actually mixing multiple streams.
 | 
| -  MixFromList(audio_frame_for_mixing, mixList, id_, use_limiter_);
 | 
| -  MixAnonomouslyFromList(audio_frame_for_mixing, additionalFramesList);
 | 
| +  // We only use the limiter if we're actually mixing multiple streams.
 | 
| +  MixFromList(audio_frame_for_mixing, mix_list, id_, use_limiter_);
 | 
| +
 | 
|    if (audio_frame_for_mixing->samples_per_channel_ == 0) {
 | 
|      // Nothing was mixed, set the audio samples to silence.
 | 
|      audio_frame_for_mixing->samples_per_channel_ = sample_size_;
 | 
| @@ -332,10 +341,13 @@ bool AudioMixerImpl::AnonymousMixabilityStatus(
 | 
|    return IsAudioSourceInList(audio_source, additional_audio_source_list_);
 | 
|  }
 | 
|  
 | 
| -AudioFrameList AudioMixerImpl::UpdateToMix(size_t maxAudioFrameCounter) const {
 | 
| +AudioFrameList AudioMixerImpl::GetNonAnonymousAudio() const {
 | 
|    RTC_DCHECK_RUN_ON(&thread_checker_);
 | 
| +  WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
 | 
| +               "GetNonAnonymousAudio()");
 | 
|    AudioFrameList result;
 | 
|    std::vector<SourceFrame> audioSourceMixingDataList;
 | 
| +  std::vector<SourceFrame> ramp_list;
 | 
|  
 | 
|    // Get audio source audio and put it in the struct vector.
 | 
|    for (MixerAudioSource* audio_source : audio_source_list_) {
 | 
| @@ -360,6 +372,7 @@ AudioFrameList AudioMixerImpl::UpdateToMix(size_t maxAudioFrameCounter) const {
 | 
|    std::sort(audioSourceMixingDataList.begin(), audioSourceMixingDataList.end(),
 | 
|              std::mem_fn(&SourceFrame::shouldMixBefore));
 | 
|  
 | 
| +  int maxAudioFrameCounter = kMaximumAmountOfMixedAudioSources;
 | 
|    // Go through list in order and put things in mixList.
 | 
|    for (SourceFrame& p : audioSourceMixingDataList) {
 | 
|      // Filter muted.
 | 
| @@ -372,34 +385,28 @@ AudioFrameList AudioMixerImpl::UpdateToMix(size_t maxAudioFrameCounter) const {
 | 
|      bool is_mixed = false;
 | 
|      if (maxAudioFrameCounter > 0) {
 | 
|        --maxAudioFrameCounter;
 | 
| -      if (!p.was_mixed_before_) {
 | 
| -        NewMixerRampIn(p.audio_frame_);
 | 
| -      }
 | 
| -      result.emplace_back(p.audio_frame_, false);
 | 
| +      result.push_back(p.audio_frame_);
 | 
| +      ramp_list.emplace_back(p.audio_source_, p.audio_frame_, false,
 | 
| +                             p.was_mixed_before_, -1);
 | 
|        is_mixed = true;
 | 
|      }
 | 
| -
 | 
| -    // Ramp out unmuted.
 | 
| -    if (p.was_mixed_before_ && !is_mixed) {
 | 
| -      NewMixerRampOut(p.audio_frame_);
 | 
| -      result.emplace_back(p.audio_frame_, false);
 | 
| -    }
 | 
| -
 | 
|      p.audio_source_->_mixHistory->SetIsMixed(is_mixed);
 | 
|    }
 | 
| +  Ramp(ramp_list);
 | 
|    return result;
 | 
|  }
 | 
|  
 | 
| -void AudioMixerImpl::GetAdditionalAudio(
 | 
| -    AudioFrameList* additionalFramesList) const {
 | 
| +AudioFrameList AudioMixerImpl::GetAnonymousAudio() const {
 | 
|    RTC_DCHECK_RUN_ON(&thread_checker_);
 | 
|    WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
 | 
| -               "GetAdditionalAudio(additionalFramesList)");
 | 
| +               "GetAnonymousAudio()");
 | 
|    // The GetAudioFrameWithMuted() callback may result in the audio source being
 | 
|    // removed from additionalAudioFramesList_. If that happens it will
 | 
|    // invalidate any iterators. Create a copy of the audio sources list such
 | 
|    // that the list of participants can be traversed safely.
 | 
| +  std::vector<SourceFrame> ramp_list;
 | 
|    MixerAudioSourceList additionalAudioSourceList;
 | 
| +  AudioFrameList result;
 | 
|    additionalAudioSourceList.insert(additionalAudioSourceList.begin(),
 | 
|                                     additional_audio_source_list_.begin(),
 | 
|                                     additional_audio_source_list_.end());
 | 
| @@ -416,13 +423,15 @@ void AudioMixerImpl::GetAdditionalAudio(
 | 
|                     "failed to GetAudioFrameWithMuted() from audio_source");
 | 
|        continue;
 | 
|      }
 | 
| -    if (audio_frame->samples_per_channel_ == 0) {
 | 
| -      // Empty frame. Don't use it.
 | 
| -      continue;
 | 
| +    if (ret != MixerAudioSource::AudioFrameInfo::kMuted) {
 | 
| +      result.push_back(audio_frame);
 | 
| +      ramp_list.emplace_back(*audio_source, audio_frame, false,
 | 
| +                             (*audio_source)->_mixHistory->IsMixed(), -1);
 | 
| +      (*audio_source)->_mixHistory->SetIsMixed(true);
 | 
|      }
 | 
| -    additionalFramesList->push_back(FrameAndMuteInfo(
 | 
| -        audio_frame, ret == MixerAudioSource::AudioFrameInfo::kMuted));
 | 
|    }
 | 
| +  Ramp(ramp_list);
 | 
| +  return result;
 | 
|  }
 | 
|  
 | 
|  bool AudioMixerImpl::IsAudioSourceInList(
 | 
| @@ -474,9 +483,8 @@ int32_t AudioMixerImpl::MixFromList(AudioFrame* mixedAudio,
 | 
|    uint32_t position = 0;
 | 
|  
 | 
|    if (audioFrameList.size() == 1) {
 | 
| -    mixedAudio->timestamp_ = audioFrameList.front().frame->timestamp_;
 | 
| -    mixedAudio->elapsed_time_ms_ =
 | 
| -        audioFrameList.front().frame->elapsed_time_ms_;
 | 
| +    mixedAudio->timestamp_ = audioFrameList.front()->timestamp_;
 | 
| +    mixedAudio->elapsed_time_ms_ = audioFrameList.front()->elapsed_time_ms_;
 | 
|    } else {
 | 
|      // TODO(wu): Issue 3390.
 | 
|      // Audio frame timestamp is only supported in one channel case.
 | 
| @@ -484,35 +492,24 @@ int32_t AudioMixerImpl::MixFromList(AudioFrame* mixedAudio,
 | 
|      mixedAudio->elapsed_time_ms_ = -1;
 | 
|    }
 | 
|  
 | 
| -  for (AudioFrameList::const_iterator iter = audioFrameList.begin();
 | 
| -       iter != audioFrameList.end(); ++iter) {
 | 
| -    if (!iter->muted) {
 | 
| -      MixFrames(mixedAudio, iter->frame, use_limiter);
 | 
| +  for (const auto& frame : audioFrameList) {
 | 
| +    RTC_DCHECK_EQ(mixedAudio->sample_rate_hz_, frame->sample_rate_hz_);
 | 
| +    RTC_DCHECK_EQ(
 | 
| +        frame->samples_per_channel_,
 | 
| +        static_cast<size_t>((mixedAudio->sample_rate_hz_ * kFrameDurationInMs) /
 | 
| +                            1000));
 | 
| +
 | 
| +    // Mix |f.frame| into |mixedAudio|, with saturation protection.
 | 
| +    // These effect is applied to |f.frame| itself prior to mixing.
 | 
| +    if (use_limiter) {
 | 
| +      // Divide by two to avoid saturation in the mixing.
 | 
| +      // This is only meaningful if the limiter will be used.
 | 
| +      *frame >>= 1;
 | 
|      }
 | 
| -
 | 
| +    RTC_DCHECK_EQ(frame->num_channels_, mixedAudio->num_channels_);
 | 
| +    *mixedAudio += *frame;
 | 
|      position++;
 | 
|    }
 | 
| -
 | 
| -  return 0;
 | 
| -}
 | 
| -
 | 
| -// TODO(andrew): consolidate this function with MixFromList.
 | 
| -int32_t AudioMixerImpl::MixAnonomouslyFromList(
 | 
| -    AudioFrame* mixedAudio,
 | 
| -    const AudioFrameList& audioFrameList) const {
 | 
| -  RTC_DCHECK_RUN_ON(&thread_checker_);
 | 
| -  WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
 | 
| -               "MixAnonomouslyFromList(mixedAudio, audioFrameList)");
 | 
| -
 | 
| -  if (audioFrameList.empty())
 | 
| -    return 0;
 | 
| -
 | 
| -  for (AudioFrameList::const_iterator iter = audioFrameList.begin();
 | 
| -       iter != audioFrameList.end(); ++iter) {
 | 
| -    if (!iter->muted) {
 | 
| -      MixFrames(mixedAudio, iter->frame, use_limiter_);
 | 
| -    }
 | 
| -  }
 | 
|    return 0;
 | 
|  }
 | 
|  
 | 
| 
 |