| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include "webrtc/modules/audio_mixer/audio_mixer_impl.h" | 11 #include "webrtc/modules/audio_mixer/audio_mixer_impl.h" |
| 12 | 12 |
| 13 #include <algorithm> | 13 #include <algorithm> |
| 14 #include <functional> | 14 #include <functional> |
| 15 #include <utility> | 15 #include <utility> |
| 16 | 16 |
| 17 #include "webrtc/base/logging.h" |
| 17 #include "webrtc/modules/audio_mixer/audio_frame_manipulator.h" | 18 #include "webrtc/modules/audio_mixer/audio_frame_manipulator.h" |
| 18 #include "webrtc/modules/utility/include/audio_frame_operations.h" | 19 #include "webrtc/modules/utility/include/audio_frame_operations.h" |
| 19 #include "webrtc/system_wrappers/include/trace.h" | 20 #include "webrtc/system_wrappers/include/trace.h" |
| 20 | 21 |
| 21 namespace webrtc { | 22 namespace webrtc { |
| 22 namespace { | 23 namespace { |
| 23 | 24 |
| 24 class SourceFrame { | 25 class SourceFrame { |
| 25 public: | 26 public: |
| 26 SourceFrame(MixerAudioSource* p, AudioFrame* a, bool m, bool was_mixed_before) | 27 SourceFrame(AudioSourceWithMixStatus* audio_source, |
| 27 : audio_source_(p), | 28 AudioFrame* audio_frame, |
| 28 audio_frame_(a), | 29 bool muted) |
| 29 muted_(m), | 30 : audio_source_(audio_source), audio_frame_(audio_frame), muted_(muted) { |
| 30 was_mixed_before_(was_mixed_before) { | |
| 31 if (!muted_) { | 31 if (!muted_) { |
| 32 energy_ = NewMixerCalculateEnergy(*a); | 32 energy_ = AudioMixerCalculateEnergy(*audio_frame); |
| 33 } | 33 } |
| 34 } | 34 } |
| 35 | 35 |
| 36 SourceFrame(MixerAudioSource* p, | 36 SourceFrame(AudioSourceWithMixStatus* audio_source, |
| 37 AudioFrame* a, | 37 AudioFrame* audio_frame, |
| 38 bool m, | 38 bool muted, |
| 39 bool was_mixed_before, | |
| 40 uint32_t energy) | 39 uint32_t energy) |
| 41 : audio_source_(p), | 40 : audio_source_(audio_source), |
| 42 audio_frame_(a), | 41 audio_frame_(audio_frame), |
| 43 muted_(m), | 42 muted_(muted), |
| 44 energy_(energy), | 43 energy_(energy) {} |
| 45 was_mixed_before_(was_mixed_before) {} | |
| 46 | 44 |
| 47 // a.shouldMixBefore(b) is used to select mixer participants. | 45 // a.ShouldMixBefore(b) is used to select mixer sources. |
| 48 bool shouldMixBefore(const SourceFrame& other) const { | 46 bool ShouldMixBefore(const SourceFrame& other) const { |
| 49 if (muted_ != other.muted_) { | 47 if (muted_ != other.muted_) { |
| 50 return other.muted_; | 48 return other.muted_; |
| 51 } | 49 } |
| 52 | 50 |
| 53 const auto our_activity = audio_frame_->vad_activity_; | 51 const auto our_activity = audio_frame_->vad_activity_; |
| 54 const auto other_activity = other.audio_frame_->vad_activity_; | 52 const auto other_activity = other.audio_frame_->vad_activity_; |
| 55 | 53 |
| 56 if (our_activity != other_activity) { | 54 if (our_activity != other_activity) { |
| 57 return our_activity == AudioFrame::kVadActive; | 55 return our_activity == AudioFrame::kVadActive; |
| 58 } | 56 } |
| 59 | 57 |
| 60 return energy_ > other.energy_; | 58 return energy_ > other.energy_; |
| 61 } | 59 } |
| 62 | 60 |
| 63 MixerAudioSource* audio_source_; | 61 AudioSourceWithMixStatus* audio_source_ = nullptr; |
| 64 AudioFrame* audio_frame_; | 62 AudioFrame* audio_frame_ = nullptr; |
| 65 bool muted_; | 63 bool muted_ = true; |
| 66 uint32_t energy_; | 64 uint32_t energy_ = 0; |
| 67 bool was_mixed_before_; | |
| 68 }; | 65 }; |
| 69 | 66 |
| 70 // Remixes a frame between stereo and mono. | 67 // Remixes a frame between stereo and mono. |
| 71 void RemixFrame(AudioFrame* frame, size_t number_of_channels) { | 68 void RemixFrame(AudioFrame* frame, size_t number_of_channels) { |
| 72 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); | 69 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); |
| 73 if (frame->num_channels_ == 1 && number_of_channels == 2) { | 70 if (frame->num_channels_ == 1 && number_of_channels == 2) { |
| 74 AudioFrameOperations::MonoToStereo(frame); | 71 AudioFrameOperations::MonoToStereo(frame); |
| 75 } else if (frame->num_channels_ == 2 && number_of_channels == 1) { | 72 } else if (frame->num_channels_ == 2 && number_of_channels == 1) { |
| 76 AudioFrameOperations::StereoToMono(frame); | 73 AudioFrameOperations::StereoToMono(frame); |
| 77 } | 74 } |
| 78 } | 75 } |
| 79 | 76 |
| 80 void Ramp(const std::vector<SourceFrame>& mixed_sources_and_frames) { | 77 void Ramp(const std::vector<SourceFrame>& mixed_sources_and_frames) { |
| 81 for (const auto& source_frame : mixed_sources_and_frames) { | 78 for (const auto& source_frame : mixed_sources_and_frames) { |
| 82 // Ramp in previously unmixed. | 79 // Ramp in previously unmixed. |
| 83 if (!source_frame.was_mixed_before_) { | 80 if (!source_frame.audio_source_->WasMixed()) { |
| 84 NewMixerRampIn(source_frame.audio_frame_); | 81 NewMixerRampIn(source_frame.audio_frame_); |
| 85 } | 82 } |
| 86 | 83 |
| 87 const bool is_mixed = source_frame.audio_source_->IsMixed(); | 84 const bool is_mixed = source_frame.audio_source_->IsMixed(); |
| 88 // Ramp out currently unmixed. | 85 // Ramp out currently unmixed. |
| 89 if (source_frame.was_mixed_before_ && !is_mixed) { | 86 if (source_frame.audio_source_->WasMixed() && !is_mixed) { |
| 90 NewMixerRampOut(source_frame.audio_frame_); | 87 NewMixerRampOut(source_frame.audio_frame_); |
| 91 } | 88 } |
| 92 } | 89 } |
| 93 } | 90 } |
| 94 | 91 |
| 95 // Mix the AudioFrames stored in audioFrameList into mixed_audio. | 92 // Mix the AudioFrames stored in audioFrameList into mixed_audio. |
| 96 int32_t MixFromList(AudioFrame* mixed_audio, | 93 int32_t MixFromList(AudioFrame* mixed_audio, |
| 97 const AudioFrameList& audio_frame_list, | 94 const AudioFrameList& audio_frame_list, |
| 98 int32_t id, | 95 int32_t id, |
| 99 bool use_limiter) { | 96 bool use_limiter) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 126 // Divide by two to avoid saturation in the mixing. | 123 // Divide by two to avoid saturation in the mixing. |
| 127 // This is only meaningful if the limiter will be used. | 124 // This is only meaningful if the limiter will be used. |
| 128 *frame >>= 1; | 125 *frame >>= 1; |
| 129 } | 126 } |
| 130 RTC_DCHECK_EQ(frame->num_channels_, mixed_audio->num_channels_); | 127 RTC_DCHECK_EQ(frame->num_channels_, mixed_audio->num_channels_); |
| 131 *mixed_audio += *frame; | 128 *mixed_audio += *frame; |
| 132 } | 129 } |
| 133 return 0; | 130 return 0; |
| 134 } | 131 } |
| 135 | 132 |
| 133 MixerAudioSourceList::const_iterator FindSourceInList( |
| 134 MixerAudioSource const* audio_source, |
| 135 MixerAudioSourceList const* audio_source_list) { |
| 136 return std::find_if(audio_source_list->begin(), audio_source_list->end(), |
| 137 [audio_source](const AudioSourceWithMixStatus& p) { |
| 138 return p.audio_source() == audio_source; |
| 139 }); |
| 140 } |
| 141 |
| 142 MixerAudioSourceList::iterator FindSourceInList( |
| 143 MixerAudioSource const* audio_source, |
| 144 MixerAudioSourceList* audio_source_list) { |
| 145 return std::find_if(audio_source_list->begin(), audio_source_list->end(), |
| 146 [audio_source](const AudioSourceWithMixStatus& p) { |
| 147 return p.audio_source() == audio_source; |
| 148 }); |
| 149 } |
| 150 |
| 136 } // namespace | 151 } // namespace |
| 137 | 152 |
| 138 std::unique_ptr<AudioMixer> AudioMixer::Create(int id) { | 153 std::unique_ptr<AudioMixer> AudioMixer::Create(int id) { |
| 139 return AudioMixerImpl::Create(id); | 154 return AudioMixerImpl::Create(id); |
| 140 } | 155 } |
| 141 | 156 |
| 142 AudioMixerImpl::AudioMixerImpl(int id, std::unique_ptr<AudioProcessing> limiter) | 157 AudioMixerImpl::AudioMixerImpl(int id, std::unique_ptr<AudioProcessing> limiter) |
| 143 : id_(id), | 158 : id_(id), |
| 144 audio_source_list_(), | 159 audio_source_list_(), |
| 145 additional_audio_source_list_(), | 160 additional_audio_source_list_(), |
| 146 num_mixed_audio_sources_(0), | 161 num_mixed_audio_sources_(0), |
| 147 use_limiter_(true), | 162 use_limiter_(true), |
| 148 time_stamp_(0), | 163 time_stamp_(0), |
| 149 limiter_(std::move(limiter)) { | 164 limiter_(std::move(limiter)) { |
| 150 SetOutputFrequency(kDefaultFrequency); | 165 SetOutputFrequency(kDefaultFrequency); |
| 151 thread_checker_.DetachFromThread(); | 166 thread_checker_.DetachFromThread(); |
| 152 } | 167 } |
| 153 | 168 |
| 154 AudioMixerImpl::~AudioMixerImpl() {} | 169 AudioMixerImpl::~AudioMixerImpl() {} |
| 155 | 170 |
| 156 std::unique_ptr<AudioMixer> AudioMixerImpl::Create(int id) { | 171 std::unique_ptr<AudioMixerImpl> AudioMixerImpl::Create(int id) { |
| 157 Config config; | 172 Config config; |
| 158 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); | 173 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); |
| 159 std::unique_ptr<AudioProcessing> limiter(AudioProcessing::Create(config)); | 174 std::unique_ptr<AudioProcessing> limiter(AudioProcessing::Create(config)); |
| 160 if (!limiter.get()) | 175 if (!limiter.get()) |
| 161 return nullptr; | 176 return nullptr; |
| 162 | 177 |
| 163 if (limiter->gain_control()->set_mode(GainControl::kFixedDigital) != | 178 if (limiter->gain_control()->set_mode(GainControl::kFixedDigital) != |
| 164 limiter->kNoError) | 179 limiter->kNoError) |
| 165 return nullptr; | 180 return nullptr; |
| 166 | 181 |
| 167 // We smoothly limit the mixed frame to -7 dbFS. -6 would correspond to the | 182 // We smoothly limit the mixed frame to -7 dbFS. -6 would correspond to the |
| 168 // divide-by-2 but -7 is used instead to give a bit of headroom since the | 183 // divide-by-2 but -7 is used instead to give a bit of headroom since the |
| 169 // AGC is not a hard limiter. | 184 // AGC is not a hard limiter. |
| 170 if (limiter->gain_control()->set_target_level_dbfs(7) != limiter->kNoError) | 185 if (limiter->gain_control()->set_target_level_dbfs(7) != limiter->kNoError) |
| 171 return nullptr; | 186 return nullptr; |
| 172 | 187 |
| 173 if (limiter->gain_control()->set_compression_gain_db(0) != limiter->kNoError) | 188 if (limiter->gain_control()->set_compression_gain_db(0) != limiter->kNoError) |
| 174 return nullptr; | 189 return nullptr; |
| 175 | 190 |
| 176 if (limiter->gain_control()->enable_limiter(true) != limiter->kNoError) | 191 if (limiter->gain_control()->enable_limiter(true) != limiter->kNoError) |
| 177 return nullptr; | 192 return nullptr; |
| 178 | 193 |
| 179 if (limiter->gain_control()->Enable(true) != limiter->kNoError) | 194 if (limiter->gain_control()->Enable(true) != limiter->kNoError) |
| 180 return nullptr; | 195 return nullptr; |
| 181 | 196 |
| 182 return std::unique_ptr<AudioMixer>( | 197 return std::unique_ptr<AudioMixerImpl>( |
| 183 new AudioMixerImpl(id, std::move(limiter))); | 198 new AudioMixerImpl(id, std::move(limiter))); |
| 184 } | 199 } |
| 185 | 200 |
| 186 void AudioMixerImpl::Mix(int sample_rate, | 201 void AudioMixerImpl::Mix(int sample_rate, |
| 187 size_t number_of_channels, | 202 size_t number_of_channels, |
| 188 AudioFrame* audio_frame_for_mixing) { | 203 AudioFrame* audio_frame_for_mixing) { |
| 189 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); | 204 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); |
| 190 RTC_DCHECK_RUN_ON(&thread_checker_); | 205 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 191 | 206 |
| 192 if (sample_rate != kNbInHz && sample_rate != kWbInHz && | 207 if (sample_rate != kNbInHz && sample_rate != kWbInHz && |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 259 | 274 |
| 260 int32_t AudioMixerImpl::SetMixabilityStatus(MixerAudioSource* audio_source, | 275 int32_t AudioMixerImpl::SetMixabilityStatus(MixerAudioSource* audio_source, |
| 261 bool mixable) { | 276 bool mixable) { |
| 262 if (!mixable) { | 277 if (!mixable) { |
| 263 // Anonymous audio sources are in a separate list. Make sure that the | 278 // Anonymous audio sources are in a separate list. Make sure that the |
| 264 // audio source is in the _audioSourceList if it is being mixed. | 279 // audio source is in the _audioSourceList if it is being mixed. |
| 265 SetAnonymousMixabilityStatus(audio_source, false); | 280 SetAnonymousMixabilityStatus(audio_source, false); |
| 266 } | 281 } |
| 267 { | 282 { |
| 268 rtc::CritScope lock(&crit_); | 283 rtc::CritScope lock(&crit_); |
| 269 const bool is_mixed = | 284 const bool is_mixed = FindSourceInList(audio_source, &audio_source_list_) != |
| 270 IsAudioSourceInList(*audio_source, audio_source_list_); | 285 audio_source_list_.end(); |
| 271 // API must be called with a new state. | 286 // API must be called with a new state. |
| 272 if (!(mixable ^ is_mixed)) { | 287 if (!(mixable ^ is_mixed)) { |
| 273 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_, | 288 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_, |
| 274 "Mixable is aready %s", is_mixed ? "ON" : "off"); | 289 "Mixable is aready %s", is_mixed ? "ON" : "off"); |
| 275 return -1; | 290 return -1; |
| 276 } | 291 } |
| 277 bool success = false; | 292 bool success = false; |
| 278 if (mixable) { | 293 if (mixable) { |
| 279 success = AddAudioSourceToList(audio_source, &audio_source_list_); | 294 success = AddAudioSourceToList(audio_source, &audio_source_list_); |
| 280 } else { | 295 } else { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 293 } | 308 } |
| 294 num_mixed_audio_sources_ = | 309 num_mixed_audio_sources_ = |
| 295 num_mixed_non_anonymous + additional_audio_source_list_.size(); | 310 num_mixed_non_anonymous + additional_audio_source_list_.size(); |
| 296 } | 311 } |
| 297 return 0; | 312 return 0; |
| 298 } | 313 } |
| 299 | 314 |
| 300 bool AudioMixerImpl::MixabilityStatus( | 315 bool AudioMixerImpl::MixabilityStatus( |
| 301 const MixerAudioSource& audio_source) const { | 316 const MixerAudioSource& audio_source) const { |
| 302 rtc::CritScope lock(&crit_); | 317 rtc::CritScope lock(&crit_); |
| 303 return IsAudioSourceInList(audio_source, audio_source_list_); | 318 return FindSourceInList(&audio_source, &audio_source_list_) != |
| 319 audio_source_list_.end(); |
| 304 } | 320 } |
| 305 | 321 |
| 306 int32_t AudioMixerImpl::SetAnonymousMixabilityStatus( | 322 int32_t AudioMixerImpl::SetAnonymousMixabilityStatus( |
| 307 MixerAudioSource* audio_source, | 323 MixerAudioSource* audio_source, |
| 308 bool anonymous) { | 324 bool anonymous) { |
| 309 rtc::CritScope lock(&crit_); | 325 rtc::CritScope lock(&crit_); |
| 310 if (IsAudioSourceInList(*audio_source, additional_audio_source_list_)) { | 326 if (FindSourceInList(audio_source, &additional_audio_source_list_) != |
| 327 additional_audio_source_list_.end()) { |
| 311 if (anonymous) { | 328 if (anonymous) { |
| 312 return 0; | 329 return 0; |
| 313 } | 330 } |
| 314 if (!RemoveAudioSourceFromList(audio_source, | 331 if (!RemoveAudioSourceFromList(audio_source, |
| 315 &additional_audio_source_list_)) { | 332 &additional_audio_source_list_)) { |
| 316 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_, | 333 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_, |
| 317 "unable to remove audio_source from anonymous list"); | 334 "unable to remove audio_source from anonymous list"); |
| 318 RTC_NOTREACHED(); | 335 RTC_NOTREACHED(); |
| 319 return -1; | 336 return -1; |
| 320 } | 337 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 334 return -1; | 351 return -1; |
| 335 } | 352 } |
| 336 return AddAudioSourceToList(audio_source, &additional_audio_source_list_) | 353 return AddAudioSourceToList(audio_source, &additional_audio_source_list_) |
| 337 ? 0 | 354 ? 0 |
| 338 : -1; | 355 : -1; |
| 339 } | 356 } |
| 340 | 357 |
| 341 bool AudioMixerImpl::AnonymousMixabilityStatus( | 358 bool AudioMixerImpl::AnonymousMixabilityStatus( |
| 342 const MixerAudioSource& audio_source) const { | 359 const MixerAudioSource& audio_source) const { |
| 343 rtc::CritScope lock(&crit_); | 360 rtc::CritScope lock(&crit_); |
| 344 return IsAudioSourceInList(audio_source, additional_audio_source_list_); | 361 return FindSourceInList(&audio_source, &additional_audio_source_list_) != |
| 362 additional_audio_source_list_.end(); |
| 345 } | 363 } |
| 346 | 364 |
| 347 AudioFrameList AudioMixerImpl::GetNonAnonymousAudio() const { | 365 AudioFrameList AudioMixerImpl::GetNonAnonymousAudio() { |
| 348 RTC_DCHECK_RUN_ON(&thread_checker_); | 366 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 349 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, | 367 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, |
| 350 "GetNonAnonymousAudio()"); | 368 "GetNonAnonymousAudio()"); |
| 351 AudioFrameList result; | 369 AudioFrameList result; |
| 352 std::vector<SourceFrame> audio_source_mixing_data_list; | 370 std::vector<SourceFrame> audio_source_mixing_data_list; |
| 353 std::vector<SourceFrame> ramp_list; | 371 std::vector<SourceFrame> ramp_list; |
| 354 | 372 |
| 355 // Get audio source audio and put it in the struct vector. | 373 // Get audio source audio and put it in the struct vector. |
| 356 for (auto* const audio_source : audio_source_list_) { | 374 for (auto& source_and_status : audio_source_list_) { |
| 357 auto audio_frame_with_info = audio_source->GetAudioFrameWithMuted( | 375 auto audio_frame_with_info = |
| 358 id_, static_cast<int>(OutputFrequency())); | 376 source_and_status.audio_source()->GetAudioFrameWithMuted( |
| 377 id_, static_cast<int>(OutputFrequency())); |
| 359 | 378 |
| 360 const auto audio_frame_info = audio_frame_with_info.audio_frame_info; | 379 const auto audio_frame_info = audio_frame_with_info.audio_frame_info; |
| 361 AudioFrame* audio_source_audio_frame = audio_frame_with_info.audio_frame; | 380 AudioFrame* audio_source_audio_frame = audio_frame_with_info.audio_frame; |
| 362 | 381 |
| 363 if (audio_frame_info == MixerAudioSource::AudioFrameInfo::kError) { | 382 if (audio_frame_info == MixerAudioSource::AudioFrameInfo::kError) { |
| 364 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_, | 383 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_, |
| 365 "failed to GetAudioFrameWithMuted() from participant"); | 384 "failed to GetAudioFrameWithMuted() from source"); |
| 366 continue; | 385 continue; |
| 367 } | 386 } |
| 368 audio_source_mixing_data_list.emplace_back( | 387 audio_source_mixing_data_list.emplace_back( |
| 369 audio_source, audio_source_audio_frame, | 388 &source_and_status, audio_source_audio_frame, |
| 370 audio_frame_info == MixerAudioSource::AudioFrameInfo::kMuted, | 389 audio_frame_info == MixerAudioSource::AudioFrameInfo::kMuted); |
| 371 audio_source->WasMixed()); | |
| 372 } | 390 } |
| 373 | 391 |
| 374 // Sort frames by sorting function. | 392 // Sort frames by sorting function. |
| 375 std::sort(audio_source_mixing_data_list.begin(), | 393 std::sort(audio_source_mixing_data_list.begin(), |
| 376 audio_source_mixing_data_list.end(), | 394 audio_source_mixing_data_list.end(), |
| 377 std::mem_fn(&SourceFrame::shouldMixBefore)); | 395 std::mem_fn(&SourceFrame::ShouldMixBefore)); |
| 378 | 396 |
| 379 int max_audio_frame_counter = kMaximumAmountOfMixedAudioSources; | 397 int max_audio_frame_counter = kMaximumAmountOfMixedAudioSources; |
| 380 | 398 |
| 381 // Go through list in order and put unmuted frames in result list. | 399 // Go through list in order and put unmuted frames in result list. |
| 382 for (const SourceFrame& p : audio_source_mixing_data_list) { | 400 for (const auto& p : audio_source_mixing_data_list) { |
| 383 // Filter muted. | 401 // Filter muted. |
| 384 if (p.muted_) { | 402 if (p.muted_) { |
| 385 p.audio_source_->SetIsMixed(false); | 403 p.audio_source_->SetIsMixed(false); |
| 386 continue; | 404 continue; |
| 387 } | 405 } |
| 388 | 406 |
| 389 // Add frame to result vector for mixing. | 407 // Add frame to result vector for mixing. |
| 390 bool is_mixed = false; | 408 bool is_mixed = false; |
| 391 if (max_audio_frame_counter > 0) { | 409 if (max_audio_frame_counter > 0) { |
| 392 --max_audio_frame_counter; | 410 --max_audio_frame_counter; |
| 393 result.push_back(p.audio_frame_); | 411 result.push_back(p.audio_frame_); |
| 394 ramp_list.emplace_back(p.audio_source_, p.audio_frame_, false, | 412 ramp_list.emplace_back(p.audio_source_, p.audio_frame_, false, -1); |
| 395 p.was_mixed_before_, -1); | |
| 396 is_mixed = true; | 413 is_mixed = true; |
| 397 } | 414 } |
| 398 p.audio_source_->SetIsMixed(is_mixed); | 415 p.audio_source_->SetIsMixed(is_mixed); |
| 399 } | 416 } |
| 400 Ramp(ramp_list); | 417 Ramp(ramp_list); |
| 401 return result; | 418 return result; |
| 402 } | 419 } |
| 403 | 420 |
| 404 AudioFrameList AudioMixerImpl::GetAnonymousAudio() const { | 421 AudioFrameList AudioMixerImpl::GetAnonymousAudio() { |
| 405 RTC_DCHECK_RUN_ON(&thread_checker_); | 422 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 406 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, | 423 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, |
| 407 "GetAnonymousAudio()"); | 424 "GetAnonymousAudio()"); |
| 408 // The GetAudioFrameWithMuted() callback may result in the audio source being | |
| 409 // removed from additionalAudioFramesList_. If that happens it will | |
| 410 // invalidate any iterators. Create a copy of the audio sources list such | |
| 411 // that the list of participants can be traversed safely. | |
| 412 std::vector<SourceFrame> ramp_list; | 425 std::vector<SourceFrame> ramp_list; |
| 413 MixerAudioSourceList additional_audio_sources_list; | |
| 414 AudioFrameList result; | 426 AudioFrameList result; |
| 415 additional_audio_sources_list.insert(additional_audio_sources_list.begin(), | 427 for (auto& source_and_status : additional_audio_source_list_) { |
| 416 additional_audio_source_list_.begin(), | |
| 417 additional_audio_source_list_.end()); | |
| 418 | |
| 419 for (const auto& audio_source : additional_audio_sources_list) { | |
| 420 const auto audio_frame_with_info = | 428 const auto audio_frame_with_info = |
| 421 audio_source->GetAudioFrameWithMuted(id_, OutputFrequency()); | 429 source_and_status.audio_source()->GetAudioFrameWithMuted( |
| 430 id_, OutputFrequency()); |
| 422 const auto ret = audio_frame_with_info.audio_frame_info; | 431 const auto ret = audio_frame_with_info.audio_frame_info; |
| 423 AudioFrame* audio_frame = audio_frame_with_info.audio_frame; | 432 AudioFrame* audio_frame = audio_frame_with_info.audio_frame; |
| 424 if (ret == MixerAudioSource::AudioFrameInfo::kError) { | 433 if (ret == MixerAudioSource::AudioFrameInfo::kError) { |
| 425 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_, | 434 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_, |
| 426 "failed to GetAudioFrameWithMuted() from audio_source"); | 435 "failed to GetAudioFrameWithMuted() from audio_source"); |
| 427 continue; | 436 continue; |
| 428 } | 437 } |
| 429 if (ret != MixerAudioSource::AudioFrameInfo::kMuted) { | 438 if (ret != MixerAudioSource::AudioFrameInfo::kMuted) { |
| 430 result.push_back(audio_frame); | 439 result.push_back(audio_frame); |
| 431 ramp_list.emplace_back(audio_source, audio_frame, false, | 440 ramp_list.emplace_back(&source_and_status, audio_frame, false, 0); |
| 432 audio_source->IsMixed(), 0); | 441 source_and_status.SetIsMixed(true); |
| 433 audio_source->SetIsMixed(true); | |
| 434 } | 442 } |
| 435 } | 443 } |
| 436 Ramp(ramp_list); | 444 Ramp(ramp_list); |
| 437 return result; | 445 return result; |
| 438 } | 446 } |
| 439 | 447 |
| 440 bool AudioMixerImpl::IsAudioSourceInList( | |
| 441 const MixerAudioSource& audio_source, | |
| 442 const MixerAudioSourceList& audio_source_list) const { | |
| 443 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, | |
| 444 "IsAudioSourceInList(audio_source,audio_source_list)"); | |
| 445 return std::find(audio_source_list.begin(), audio_source_list.end(), | |
| 446 &audio_source) != audio_source_list.end(); | |
| 447 } | |
| 448 | |
| 449 bool AudioMixerImpl::AddAudioSourceToList( | 448 bool AudioMixerImpl::AddAudioSourceToList( |
| 450 MixerAudioSource* audio_source, | 449 MixerAudioSource* audio_source, |
| 451 MixerAudioSourceList* audio_source_list) const { | 450 MixerAudioSourceList* audio_source_list) const { |
| 452 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, | 451 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, |
| 453 "AddAudioSourceToList(audio_source, audio_source_list)"); | 452 "AddAudioSourceToList(audio_source, audio_source_list)"); |
| 454 audio_source_list->push_back(audio_source); | 453 audio_source_list->emplace_back(audio_source); |
| 455 // Make sure that the mixed status is correct for new MixerAudioSource. | |
| 456 audio_source->ResetMixedStatus(); | |
| 457 return true; | 454 return true; |
| 458 } | 455 } |
| 459 | 456 |
| 460 bool AudioMixerImpl::RemoveAudioSourceFromList( | 457 bool AudioMixerImpl::RemoveAudioSourceFromList( |
| 461 MixerAudioSource* audio_source, | 458 MixerAudioSource* audio_source, |
| 462 MixerAudioSourceList* audio_source_list) const { | 459 MixerAudioSourceList* audio_source_list) const { |
| 463 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, | 460 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, |
| 464 "RemoveAudioSourceFromList(audio_source, audio_source_list)"); | 461 "RemoveAudioSourceFromList(audio_source, audio_source_list)"); |
| 465 const auto iter = std::find(audio_source_list->begin(), | 462 const auto iter = FindSourceInList(audio_source, audio_source_list); |
| 466 audio_source_list->end(), audio_source); | |
| 467 if (iter != audio_source_list->end()) { | 463 if (iter != audio_source_list->end()) { |
| 468 audio_source_list->erase(iter); | 464 audio_source_list->erase(iter); |
| 469 // AudioSource is no longer mixed, reset to default. | |
| 470 audio_source->ResetMixedStatus(); | |
| 471 return true; | 465 return true; |
| 472 } else { | 466 } else { |
| 473 return false; | 467 return false; |
| 474 } | 468 } |
| 475 } | 469 } |
| 476 | 470 |
| 477 bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixed_audio) const { | 471 bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixed_audio) const { |
| 478 RTC_DCHECK_RUN_ON(&thread_checker_); | 472 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 479 if (!use_limiter_) { | 473 if (!use_limiter_) { |
| 480 return true; | 474 return true; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 return level; | 506 return level; |
| 513 } | 507 } |
| 514 | 508 |
| 515 int AudioMixerImpl::GetOutputAudioLevelFullRange() { | 509 int AudioMixerImpl::GetOutputAudioLevelFullRange() { |
| 516 RTC_DCHECK_RUN_ON(&thread_checker_); | 510 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 517 const int level = audio_level_.LevelFullRange(); | 511 const int level = audio_level_.LevelFullRange(); |
| 518 WEBRTC_TRACE(kTraceStateInfo, kTraceAudioMixerServer, id_, | 512 WEBRTC_TRACE(kTraceStateInfo, kTraceAudioMixerServer, id_, |
| 519 "GetAudioOutputLevelFullRange() => level=%d", level); | 513 "GetAudioOutputLevelFullRange() => level=%d", level); |
| 520 return level; | 514 return level; |
| 521 } | 515 } |
| 516 |
| 517 bool AudioMixerImpl::GetAudioSourceMixabilityStatusForTest( |
| 518 MixerAudioSource* audio_source) { |
| 519 RTC_DCHECK_RUN_ON(&thread_checker_); |
| 520 rtc::CritScope lock(&crit_); |
| 521 |
| 522 const auto non_anonymous_iter = |
| 523 FindSourceInList(audio_source, &audio_source_list_); |
| 524 if (non_anonymous_iter != audio_source_list_.end()) { |
| 525 return non_anonymous_iter->IsMixed(); |
| 526 } |
| 527 |
| 528 const auto anonymous_iter = |
| 529 FindSourceInList(audio_source, &additional_audio_source_list_); |
| 530 if (anonymous_iter != audio_source_list_.end()) { |
| 531 return anonymous_iter->IsMixed(); |
| 532 } |
| 533 |
| 534 LOG_T_F(LS_ERROR) << "Audio source unknown"; |
| 535 return false; |
| 536 } |
| 522 } // namespace webrtc | 537 } // namespace webrtc |
| OLD | NEW |