Index: webrtc/modules/audio_mixer/source/new_audio_conference_mixer_impl.cc |
diff --git a/webrtc/modules/audio_mixer/source/new_audio_conference_mixer_impl.cc b/webrtc/modules/audio_mixer/source/new_audio_conference_mixer_impl.cc |
index 19991bcb2a70ed937c253127e9c0e6fc5bde58fb..a3814873d5200cc61506c8c455d873e80abde5b2 100644 |
--- a/webrtc/modules/audio_mixer/source/new_audio_conference_mixer_impl.cc |
+++ b/webrtc/modules/audio_mixer/source/new_audio_conference_mixer_impl.cc |
@@ -22,12 +22,43 @@ |
namespace webrtc { |
namespace { |
-struct ParticipantFrameStruct { |
- ParticipantFrameStruct(MixerAudioSource* p, AudioFrame* a, bool m) |
- : participant(p), audioFrame(a), muted(m) {} |
- MixerAudioSource* participant; |
- AudioFrame* audioFrame; |
- bool muted; |
+class ParticipantFrameStruct { |
ossu
2016/07/08 11:02:14
I don't think we suffix structs with Struct. Proba
aleloi
2016/07/08 13:45:23
Done.
|
+ public: |
+ ParticipantFrameStruct(MixerAudioSource* p, |
+ AudioFrame* a, |
+ bool m, |
+ bool was_mixed_before) |
+ : participant_(p), |
+ audio_frame_(a), |
+ muted_(m), |
+ was_mixed_before_(was_mixed_before) { |
+ if (!muted_) { |
+ energy_ = CalculateEnergy(*a); |
+ } |
+ } |
+ |
+ // a.shouldMixAfter(b) is used to select mixer participants. |
+ bool shouldMixAfter(const ParticipantFrameStruct& other) const { |
+ if (muted_ != other.muted_) { |
+ return muted_ && !other.muted_; |
ossu
2016/07/08 11:02:14
wh... what? Returning muted should be enough here.
aleloi
2016/07/08 13:45:23
Done. You are right, it's shorter.
|
+ } |
+ |
+ auto our_activity = audio_frame_->vad_activity_, |
+ other_activity = other.audio_frame_->vad_activity_; |
ossu
2016/07/08 11:02:14
I'm not sure if this is in the style guide, but I'
aleloi
2016/07/08 13:45:24
Done.
|
+ if (our_activity != other_activity) { |
+ return (our_activity == AudioFrame::kVadPassive || |
+ our_activity == AudioFrame::kVadUnknown) && |
+ other_activity == AudioFrame::kVadActive; |
+ } |
+ |
+ return energy_ < other.energy_; |
+ } |
+ |
+ MixerAudioSource* participant_; |
ossu
2016/07/08 11:02:13
participant or source? Pick one! :)
|
+ AudioFrame* audio_frame_; |
+ bool muted_; |
+ uint32_t energy_; |
+ bool was_mixed_before_; |
}; |
typedef std::list<ParticipantFrameStruct*> ParticipantFrameStructList; |
@@ -183,7 +214,6 @@ void NewAudioConferenceMixerImpl::Mix(AudioFrame* audio_frame_for_mixing) { |
lowFreq = 32000; |
} |
if (lowFreq <= 0) { |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
ossu
2016/07/08 11:02:14
Why is this no longer useful?
|
return; |
} else { |
switch (lowFreq) { |
@@ -210,16 +240,13 @@ void NewAudioConferenceMixerImpl::Mix(AudioFrame* audio_frame_for_mixing) { |
default: |
RTC_DCHECK(false); |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
return; |
} |
} |
- UpdateToMix(&mixList, &rampOutList, &mixedParticipantsMap, |
- &remainingParticipantsAllowedToMix); |
- |
+ mixList = UpdateToMix(remainingParticipantsAllowedToMix); |
ossu
2016/07/08 11:02:14
You could just use kMaximumAmountOfMixedParticipan
aleloi
2016/07/08 13:45:24
Done.
|
+ remainingParticipantsAllowedToMix -= mixList.size(); |
ossu
2016/07/08 11:02:14
Who cares? It's never used again, is it?
aleloi
2016/07/08 13:45:24
Removed. Thanks!
|
GetAdditionalAudio(&additionalFramesList); |
- UpdateMixedStatus(mixedParticipantsMap); |
} |
// TODO(henrike): it might be better to decide the number of channels |
@@ -258,10 +285,6 @@ void NewAudioConferenceMixerImpl::Mix(AudioFrame* audio_frame_for_mixing) { |
} |
} |
- ClearAudioFrameList(&mixList); |
ossu
2016/07/08 11:02:14
So I guess this used to be necessary to hand the f
|
- ClearAudioFrameList(&rampOutList); |
- ClearAudioFrameList(&additionalFramesList); |
- RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
return; |
} |
@@ -426,173 +449,65 @@ int32_t NewAudioConferenceMixerImpl::GetLowestMixingFrequencyFromList( |
return highestFreq; |
} |
-void NewAudioConferenceMixerImpl::UpdateToMix( |
- AudioFrameList* mixList, |
- AudioFrameList* rampOutList, |
- std::map<int, MixerAudioSource*>* mixParticipantList, |
- size_t* maxAudioFrameCounter) const { |
- WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, |
- "UpdateToMix(mixList,rampOutList,mixParticipantList,%d)", |
- *maxAudioFrameCounter); |
- const size_t mixListStartSize = mixList->size(); |
- AudioFrameList activeList; |
- // Struct needed by the passive lists to keep track of which AudioFrame |
- // belongs to which MixerAudioSource. |
- ParticipantFrameStructList passiveWasNotMixedList; |
- ParticipantFrameStructList passiveWasMixedList; |
- for (MixerAudioSourceList::const_iterator participant = |
- _participantList.begin(); |
- participant != _participantList.end(); ++participant) { |
- // Stop keeping track of passive participants if there are already |
- // enough participants available (they wont be mixed anyway). |
- bool mustAddToPassiveList = |
- (*maxAudioFrameCounter > |
- (activeList.size() + passiveWasMixedList.size() + |
- passiveWasNotMixedList.size())); |
- |
- bool wasMixed = false; |
- wasMixed = (*participant)->_mixHistory->WasMixed(); |
+AudioFrameList NewAudioConferenceMixerImpl::UpdateToMix( |
+ size_t maxAudioFrameCounter) const { |
+ AudioFrameList result; |
+ std::vector<ParticipantFrameStruct> participantMixingDataList; |
- auto audio_frame_with_info = |
- (*participant)->GetAudioFrameWithMuted(_id, _outputFrequency); |
+ // Get participant audio and put it in the struct vector. |
+ for (MixerAudioSource* participant : _participantList) { |
+ auto audio_frame_with_info = participant->GetAudioFrameWithMuted( |
ossu
2016/07/08 11:02:14
Hmm... reading this, I'm thinking AudioFrameWithIn
aleloi
2016/07/08 13:45:24
I agree. Changed.
|
+ _id, static_cast<int>(_outputFrequency)); |
- auto ret = audio_frame_with_info.audio_frame_info; |
- AudioFrame* audio_frame = audio_frame_with_info.audio_frame; |
- if (ret == MixerAudioSource::AudioFrameInfo::kError) { |
- continue; |
- } |
- const bool muted = (ret == MixerAudioSource::AudioFrameInfo::kMuted); |
- if (_participantList.size() != 1) { |
- // TODO(wu): Issue 3390, add support for multiple participants case. |
- audio_frame->ntp_time_ms_ = -1; |
- } |
+ auto audio_frame_info = audio_frame_with_info.audio_frame_info; |
+ AudioFrame* participant_audio_frame = audio_frame_with_info.audio_frame; |
- // TODO(henrike): this assert triggers in some test cases where SRTP is |
- // used which prevents NetEQ from making a VAD. Temporarily disable this |
- // assert until the problem is fixed on a higher level. |
- // RTC_DCHECK(audio_frame->vad_activity_ != AudioFrame::kVadUnknown); |
- if (audio_frame->vad_activity_ == AudioFrame::kVadUnknown) { |
+ if (audio_frame_info == MixerAudioSource::AudioFrameInfo::kError) { |
WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, |
- "invalid VAD state from participant"); |
+ "failed to GetAudioFrameWithMuted() from participant"); |
+ continue; |
} |
+ participantMixingDataList.emplace_back( |
+ participant, participant_audio_frame, |
+ audio_frame_info == MixerAudioSource::AudioFrameInfo::kMuted, |
+ participant->_mixHistory->WasMixed()); |
+ } |
- if (audio_frame->vad_activity_ == AudioFrame::kVadActive) { |
- if (!wasMixed && !muted) { |
- RampIn(*audio_frame); |
- } |
+ // Sort frames by sorting function. |
+ std::sort( |
ossu
2016/07/08 11:02:13
Suggestion: rework shouldMixAfter into shouldMixBe
aleloi
2016/07/08 13:45:24
Done. Btw, I got the impression from reading the s
ossu
2016/07/08 13:58:34
That makes perfect sense. Reading up on that, I mi
|
+ participantMixingDataList.begin(), participantMixingDataList.end(), |
+ [](const ParticipantFrameStruct& a, const ParticipantFrameStruct& b) { |
+ return b.shouldMixAfter(a); |
+ }); |
+ |
+ // Go through list in order and put things in mixList. |
+ for (ParticipantFrameStruct& p : participantMixingDataList) { |
+ // Filter muted. |
+ if (p.muted_) { |
+ p.participant_->_mixHistory->SetIsMixed(false); |
+ continue; |
+ } |
- if (activeList.size() >= *maxAudioFrameCounter) { |
- // There are already more active participants than should be |
- // mixed. Only keep the ones with the highest energy. |
- AudioFrameList::iterator replaceItem; |
- uint32_t lowestEnergy = muted ? 0 : CalculateEnergy(*audio_frame); |
- |
- bool found_replace_item = false; |
- for (AudioFrameList::iterator iter = activeList.begin(); |
- iter != activeList.end(); ++iter) { |
- const uint32_t energy = muted ? 0 : CalculateEnergy(*iter->frame); |
- if (energy < lowestEnergy) { |
- replaceItem = iter; |
- lowestEnergy = energy; |
- found_replace_item = true; |
- } |
- } |
- if (found_replace_item) { |
- RTC_DCHECK(!muted); // Cannot replace with a muted frame. |
- FrameAndMuteInfo replaceFrame = *replaceItem; |
- |
- bool replaceWasMixed = false; |
- std::map<int, MixerAudioSource*>::const_iterator it = |
- mixParticipantList->find(replaceFrame.frame->id_); |
- |
- // When a frame is pushed to |activeList| it is also pushed |
- // to mixParticipantList with the frame's id. This means |
- // that the Find call above should never fail. |
- RTC_DCHECK(it != mixParticipantList->end()); |
- replaceWasMixed = it->second->_mixHistory->WasMixed(); |
- |
- mixParticipantList->erase(replaceFrame.frame->id_); |
- activeList.erase(replaceItem); |
- |
- activeList.push_front(FrameAndMuteInfo(audio_frame, muted)); |
- (*mixParticipantList)[audio_frame->id_] = *participant; |
- RTC_DCHECK(mixParticipantList->size() <= |
- kMaximumAmountOfMixedParticipants); |
- |
- if (replaceWasMixed) { |
- if (!replaceFrame.muted) { |
- RampOut(*replaceFrame.frame); |
- } |
- rampOutList->push_back(replaceFrame); |
- RTC_DCHECK(rampOutList->size() <= |
- kMaximumAmountOfMixedParticipants); |
- } |
- } else { |
- if (wasMixed) { |
- if (!muted) { |
- RampOut(*audio_frame); |
- } |
- rampOutList->push_back(FrameAndMuteInfo(audio_frame, muted)); |
- assert(rampOutList->size() <= kMaximumAmountOfMixedParticipants); |
- } |
- } |
- } else { |
- activeList.push_front(FrameAndMuteInfo(audio_frame, muted)); |
- (*mixParticipantList)[audio_frame->id_] = *participant; |
- RTC_DCHECK(mixParticipantList->size() <= |
- kMaximumAmountOfMixedParticipants); |
- } |
- } else { |
- if (wasMixed) { |
- ParticipantFrameStruct* part_struct = |
- new ParticipantFrameStruct(*participant, audio_frame, muted); |
- passiveWasMixedList.push_back(part_struct); |
- } else if (mustAddToPassiveList) { |
- if (!muted) { |
- RampIn(*audio_frame); |
- } |
- ParticipantFrameStruct* part_struct = |
- new ParticipantFrameStruct(*participant, audio_frame, muted); |
- passiveWasNotMixedList.push_back(part_struct); |
+ // Add frame to result vectorfor mixing. |
ossu
2016/07/08 11:02:14
vectorfor -> vector for
aleloi
2016/07/08 13:45:23
Done.
|
+ bool is_mixed = false; |
+ if (maxAudioFrameCounter > 0) { |
+ --maxAudioFrameCounter; |
+ if (!p.was_mixed_before_) { |
+ RampIn(*p.audio_frame_); |
} |
+ result.emplace_back(p.audio_frame_, false); |
+ is_mixed = true; |
} |
- } |
- RTC_DCHECK(activeList.size() <= *maxAudioFrameCounter); |
- // At this point it is known which participants should be mixed. Transfer |
- // this information to this functions output parameters. |
- for (AudioFrameList::const_iterator iter = activeList.begin(); |
- iter != activeList.end(); ++iter) { |
- mixList->push_back(*iter); |
- } |
- activeList.clear(); |
- // Always mix a constant number of AudioFrames. If there aren't enough |
- // active participants mix passive ones. Starting with those that was mixed |
- // last iteration. |
- for (ParticipantFrameStructList::const_iterator iter = |
- passiveWasMixedList.begin(); |
- iter != passiveWasMixedList.end(); ++iter) { |
- if (mixList->size() < *maxAudioFrameCounter + mixListStartSize) { |
- mixList->push_back(FrameAndMuteInfo((*iter)->audioFrame, (*iter)->muted)); |
- (*mixParticipantList)[(*iter)->audioFrame->id_] = (*iter)->participant; |
- RTC_DCHECK(mixParticipantList->size() <= |
- kMaximumAmountOfMixedParticipants); |
- } |
- delete *iter; |
- } |
- // And finally the ones that have not been mixed for a while. |
- for (ParticipantFrameStructList::const_iterator iter = |
- passiveWasNotMixedList.begin(); |
- iter != passiveWasNotMixedList.end(); ++iter) { |
- if (mixList->size() < *maxAudioFrameCounter + mixListStartSize) { |
- mixList->push_back(FrameAndMuteInfo((*iter)->audioFrame, (*iter)->muted)); |
- (*mixParticipantList)[(*iter)->audioFrame->id_] = (*iter)->participant; |
- RTC_DCHECK(mixParticipantList->size() <= |
- kMaximumAmountOfMixedParticipants); |
+ |
+ // Ramp out unmuted. |
+ if (p.was_mixed_before_ && !is_mixed) { |
+ RampOut(*p.audio_frame_); |
+ result.emplace_back(p.audio_frame_, false); |
} |
- delete *iter; |
+ |
+ p.participant_->_mixHistory->SetIsMixed(is_mixed); |
} |
- RTC_DCHECK(*maxAudioFrameCounter + mixListStartSize >= mixList->size()); |
- *maxAudioFrameCounter += mixListStartSize - mixList->size(); |
+ return result; |
} |
void NewAudioConferenceMixerImpl::GetAdditionalAudio( |
ossu
2016/07/08 11:02:14
Not necessary for this CL, but this should be chan
aleloi
2016/07/08 13:45:23
Acknowledged.
|
@@ -629,37 +544,6 @@ void NewAudioConferenceMixerImpl::GetAdditionalAudio( |
} |
} |
-void NewAudioConferenceMixerImpl::UpdateMixedStatus( |
- const std::map<int, MixerAudioSource*>& mixedParticipantsMap) const { |
- WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, |
- "UpdateMixedStatus(mixedParticipantsMap)"); |
- RTC_DCHECK(mixedParticipantsMap.size() <= kMaximumAmountOfMixedParticipants); |
- |
- // Loop through all participants. If they are in the mix map they |
- // were mixed. |
- for (MixerAudioSourceList::const_iterator participant = |
- _participantList.begin(); |
- participant != _participantList.end(); ++participant) { |
- bool isMixed = false; |
- for (std::map<int, MixerAudioSource*>::const_iterator it = |
- mixedParticipantsMap.begin(); |
- it != mixedParticipantsMap.end(); ++it) { |
- if (it->second == *participant) { |
- isMixed = true; |
- break; |
- } |
- } |
- (*participant)->_mixHistory->SetIsMixed(isMixed); |
- } |
-} |
- |
-void NewAudioConferenceMixerImpl::ClearAudioFrameList( |
- AudioFrameList* audioFrameList) const { |
- WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, |
- "ClearAudioFrameList(audioFrameList)"); |
- audioFrameList->clear(); |
-} |
- |
bool NewAudioConferenceMixerImpl::IsParticipantInList( |
const MixerAudioSource& participant, |
const MixerAudioSourceList& participantList) const { |