| 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 |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 MixerAudioSource::MixerAudioSource() : _mixHistory(new NewMixHistory()) {} | 91 MixerAudioSource::MixerAudioSource() : _mixHistory(new NewMixHistory()) {} |
| 92 | 92 |
| 93 MixerAudioSource::~MixerAudioSource() { | 93 MixerAudioSource::~MixerAudioSource() { |
| 94 delete _mixHistory; | 94 delete _mixHistory; |
| 95 } | 95 } |
| 96 | 96 |
| 97 bool MixerAudioSource::IsMixed() const { | 97 bool MixerAudioSource::IsMixed() const { |
| 98 return _mixHistory->IsMixed(); | 98 return _mixHistory->IsMixed(); |
| 99 } | 99 } |
| 100 | 100 |
| 101 NewMixHistory::NewMixHistory() : _isMixed(0) {} | 101 NewMixHistory::NewMixHistory() : is_mixed_(0) {} |
| 102 | 102 |
| 103 NewMixHistory::~NewMixHistory() {} | 103 NewMixHistory::~NewMixHistory() {} |
| 104 | 104 |
| 105 bool NewMixHistory::IsMixed() const { | 105 bool NewMixHistory::IsMixed() const { |
| 106 return _isMixed; | 106 return is_mixed_; |
| 107 } | 107 } |
| 108 | 108 |
| 109 bool NewMixHistory::WasMixed() const { | 109 bool NewMixHistory::WasMixed() const { |
| 110 // Was mixed is the same as is mixed depending on perspective. This function | 110 // Was mixed is the same as is mixed depending on perspective. This function |
| 111 // is for the perspective of NewAudioConferenceMixerImpl. | 111 // is for the perspective of NewAudioConferenceMixerImpl. |
| 112 return IsMixed(); | 112 return IsMixed(); |
| 113 } | 113 } |
| 114 | 114 |
| 115 int32_t NewMixHistory::SetIsMixed(const bool mixed) { | 115 int32_t NewMixHistory::SetIsMixed(const bool mixed) { |
| 116 _isMixed = mixed; | 116 is_mixed_ = mixed; |
| 117 return 0; | 117 return 0; |
| 118 } | 118 } |
| 119 | 119 |
| 120 void NewMixHistory::ResetMixedStatus() { | 120 void NewMixHistory::ResetMixedStatus() { |
| 121 _isMixed = false; | 121 is_mixed_ = false; |
| 122 } | 122 } |
| 123 | 123 |
| 124 NewAudioConferenceMixer* NewAudioConferenceMixer::Create(int id) { | 124 NewAudioConferenceMixer* NewAudioConferenceMixer::Create(int id) { |
| 125 NewAudioConferenceMixerImpl* mixer = new NewAudioConferenceMixerImpl(id); | 125 NewAudioConferenceMixerImpl* mixer = new NewAudioConferenceMixerImpl(id); |
| 126 if (!mixer->Init()) { | 126 if (!mixer->Init()) { |
| 127 delete mixer; | 127 delete mixer; |
| 128 return NULL; | 128 return NULL; |
| 129 } | 129 } |
| 130 return mixer; | 130 return mixer; |
| 131 } | 131 } |
| 132 | 132 |
| 133 NewAudioConferenceMixerImpl::NewAudioConferenceMixerImpl(int id) | 133 NewAudioConferenceMixerImpl::NewAudioConferenceMixerImpl(int id) |
| 134 : _id(id), | 134 : id_(id), |
| 135 _outputFrequency(kDefaultFrequency), | 135 output_frequency_(kDefaultFrequency), |
| 136 _sampleSize(0), | 136 sample_size_(0), |
| 137 audio_source_list_(), | 137 audio_source_list_(), |
| 138 additional_audio_source_list_(), | 138 additional_audio_source_list_(), |
| 139 num_mixed_audio_sources_(0), | 139 num_mixed_audio_sources_(0), |
| 140 use_limiter_(true), | 140 use_limiter_(true), |
| 141 _timeStamp(0) { | 141 time_stamp_(0) { |
| 142 thread_checker_.DetachFromThread(); | 142 thread_checker_.DetachFromThread(); |
| 143 } | 143 } |
| 144 | 144 |
| 145 bool NewAudioConferenceMixerImpl::Init() { | 145 bool NewAudioConferenceMixerImpl::Init() { |
| 146 _crit.reset(CriticalSectionWrapper::CreateCriticalSection()); | 146 crit_.reset(CriticalSectionWrapper::CreateCriticalSection()); |
| 147 if (_crit.get() == NULL) | 147 if (crit_.get() == NULL) |
| 148 return false; | 148 return false; |
| 149 | 149 |
| 150 _cbCrit.reset(CriticalSectionWrapper::CreateCriticalSection()); | 150 cb_crit_.reset(CriticalSectionWrapper::CreateCriticalSection()); |
| 151 if (_cbCrit.get() == NULL) | 151 if (cb_crit_.get() == NULL) |
| 152 return false; | 152 return false; |
| 153 | 153 |
| 154 Config config; | 154 Config config; |
| 155 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); | 155 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); |
| 156 _limiter.reset(AudioProcessing::Create(config)); | 156 limiter_.reset(AudioProcessing::Create(config)); |
| 157 if (!_limiter.get()) | 157 if (!limiter_.get()) |
| 158 return false; | 158 return false; |
| 159 | 159 |
| 160 if (SetOutputFrequency(kDefaultFrequency) == -1) | 160 if (SetOutputFrequency(kDefaultFrequency) == -1) |
| 161 return false; | 161 return false; |
| 162 | 162 |
| 163 if (_limiter->gain_control()->set_mode(GainControl::kFixedDigital) != | 163 if (limiter_->gain_control()->set_mode(GainControl::kFixedDigital) != |
| 164 _limiter->kNoError) | 164 limiter_->kNoError) |
| 165 return false; | 165 return false; |
| 166 | 166 |
| 167 // We smoothly limit the mixed frame to -7 dbFS. -6 would correspond to the | 167 // 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 | 168 // divide-by-2 but -7 is used instead to give a bit of headroom since the |
| 169 // AGC is not a hard limiter. | 169 // AGC is not a hard limiter. |
| 170 if (_limiter->gain_control()->set_target_level_dbfs(7) != _limiter->kNoError) | 170 if (limiter_->gain_control()->set_target_level_dbfs(7) != limiter_->kNoError) |
| 171 return false; | 171 return false; |
| 172 | 172 |
| 173 if (_limiter->gain_control()->set_compression_gain_db(0) != | 173 if (limiter_->gain_control()->set_compression_gain_db(0) != |
| 174 _limiter->kNoError) | 174 limiter_->kNoError) |
| 175 return false; | 175 return false; |
| 176 | 176 |
| 177 if (_limiter->gain_control()->enable_limiter(true) != _limiter->kNoError) | 177 if (limiter_->gain_control()->enable_limiter(true) != limiter_->kNoError) |
| 178 return false; | 178 return false; |
| 179 | 179 |
| 180 if (_limiter->gain_control()->Enable(true) != _limiter->kNoError) | 180 if (limiter_->gain_control()->Enable(true) != limiter_->kNoError) |
| 181 return false; | 181 return false; |
| 182 | 182 |
| 183 return true; | 183 return true; |
| 184 } | 184 } |
| 185 | 185 |
| 186 void NewAudioConferenceMixerImpl::Mix(int sample_rate, | 186 void NewAudioConferenceMixerImpl::Mix(int sample_rate, |
| 187 size_t number_of_channels, | 187 size_t number_of_channels, |
| 188 AudioFrame* audio_frame_for_mixing) { | 188 AudioFrame* audio_frame_for_mixing) { |
| 189 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); | 189 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); |
| 190 size_t remainingAudioSourcesAllowedToMix = kMaximumAmountOfMixedAudioSources; | 190 size_t remainingAudioSourcesAllowedToMix = kMaximumAmountOfMixedAudioSources; |
| 191 RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 191 RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| 192 AudioFrameList mixList; | 192 AudioFrameList mixList; |
| 193 AudioFrameList additionalFramesList; | 193 AudioFrameList additionalFramesList; |
| 194 std::map<int, MixerAudioSource*> mixedAudioSourcesMap; | 194 std::map<int, MixerAudioSource*> mixedAudioSourcesMap; |
| 195 { | 195 { |
| 196 CriticalSectionScoped cs(_cbCrit.get()); | 196 CriticalSectionScoped cs(cb_crit_.get()); |
| 197 Frequency mixing_frequency; | 197 Frequency mixing_frequency; |
| 198 | 198 |
| 199 switch (sample_rate) { | 199 switch (sample_rate) { |
| 200 case 8000: | 200 case 8000: |
| 201 mixing_frequency = kNbInHz; | 201 mixing_frequency = kNbInHz; |
| 202 break; | 202 break; |
| 203 case 16000: | 203 case 16000: |
| 204 mixing_frequency = kWbInHz; | 204 mixing_frequency = kWbInHz; |
| 205 break; | 205 break; |
| 206 case 32000: | 206 case 32000: |
| (...skipping 17 matching lines...) Expand all Loading... |
| 224 } | 224 } |
| 225 | 225 |
| 226 for (FrameAndMuteInfo& frame_and_mute : mixList) { | 226 for (FrameAndMuteInfo& frame_and_mute : mixList) { |
| 227 RemixFrame(frame_and_mute.frame, number_of_channels); | 227 RemixFrame(frame_and_mute.frame, number_of_channels); |
| 228 } | 228 } |
| 229 for (FrameAndMuteInfo& frame_and_mute : additionalFramesList) { | 229 for (FrameAndMuteInfo& frame_and_mute : additionalFramesList) { |
| 230 RemixFrame(frame_and_mute.frame, number_of_channels); | 230 RemixFrame(frame_and_mute.frame, number_of_channels); |
| 231 } | 231 } |
| 232 | 232 |
| 233 audio_frame_for_mixing->UpdateFrame( | 233 audio_frame_for_mixing->UpdateFrame( |
| 234 -1, _timeStamp, NULL, 0, _outputFrequency, AudioFrame::kNormalSpeech, | 234 -1, time_stamp_, NULL, 0, output_frequency_, AudioFrame::kNormalSpeech, |
| 235 AudioFrame::kVadPassive, number_of_channels); | 235 AudioFrame::kVadPassive, number_of_channels); |
| 236 | 236 |
| 237 _timeStamp += static_cast<uint32_t>(_sampleSize); | 237 time_stamp_ += static_cast<uint32_t>(sample_size_); |
| 238 | 238 |
| 239 use_limiter_ = num_mixed_audio_sources_ > 1 && | 239 use_limiter_ = num_mixed_audio_sources_ > 1 && |
| 240 _outputFrequency <= AudioProcessing::kMaxNativeSampleRateHz; | 240 output_frequency_ <= AudioProcessing::kMaxNativeSampleRateHz; |
| 241 | 241 |
| 242 // We only use the limiter if it supports the output sample rate and | 242 // We only use the limiter if it supports the output sample rate and |
| 243 // we're actually mixing multiple streams. | 243 // we're actually mixing multiple streams. |
| 244 MixFromList(audio_frame_for_mixing, mixList, _id, use_limiter_); | 244 MixFromList(audio_frame_for_mixing, mixList, id_, use_limiter_); |
| 245 | 245 |
| 246 { | 246 { |
| 247 CriticalSectionScoped cs(_crit.get()); | 247 CriticalSectionScoped cs(crit_.get()); |
| 248 MixAnonomouslyFromList(audio_frame_for_mixing, additionalFramesList); | 248 MixAnonomouslyFromList(audio_frame_for_mixing, additionalFramesList); |
| 249 | 249 |
| 250 if (audio_frame_for_mixing->samples_per_channel_ == 0) { | 250 if (audio_frame_for_mixing->samples_per_channel_ == 0) { |
| 251 // Nothing was mixed, set the audio samples to silence. | 251 // Nothing was mixed, set the audio samples to silence. |
| 252 audio_frame_for_mixing->samples_per_channel_ = _sampleSize; | 252 audio_frame_for_mixing->samples_per_channel_ = sample_size_; |
| 253 audio_frame_for_mixing->Mute(); | 253 audio_frame_for_mixing->Mute(); |
| 254 } else { | 254 } else { |
| 255 // Only call the limiter if we have something to mix. | 255 // Only call the limiter if we have something to mix. |
| 256 LimitMixedAudio(audio_frame_for_mixing); | 256 LimitMixedAudio(audio_frame_for_mixing); |
| 257 } | 257 } |
| 258 } | 258 } |
| 259 return; | 259 return; |
| 260 } | 260 } |
| 261 | 261 |
| 262 int32_t NewAudioConferenceMixerImpl::SetOutputFrequency( | 262 int32_t NewAudioConferenceMixerImpl::SetOutputFrequency( |
| 263 const Frequency& frequency) { | 263 const Frequency& frequency) { |
| 264 CriticalSectionScoped cs(_crit.get()); | 264 CriticalSectionScoped cs(crit_.get()); |
| 265 | 265 |
| 266 _outputFrequency = frequency; | 266 output_frequency_ = frequency; |
| 267 _sampleSize = | 267 sample_size_ = |
| 268 static_cast<size_t>((_outputFrequency * kProcessPeriodicityInMs) / 1000); | 268 static_cast<size_t>((output_frequency_ * kProcessPeriodicityInMs) / 1000); |
| 269 | 269 |
| 270 return 0; | 270 return 0; |
| 271 } | 271 } |
| 272 | 272 |
| 273 NewAudioConferenceMixer::Frequency | 273 NewAudioConferenceMixer::Frequency |
| 274 NewAudioConferenceMixerImpl::OutputFrequency() const { | 274 NewAudioConferenceMixerImpl::OutputFrequency() const { |
| 275 CriticalSectionScoped cs(_crit.get()); | 275 CriticalSectionScoped cs(crit_.get()); |
| 276 return _outputFrequency; | 276 return output_frequency_; |
| 277 } | 277 } |
| 278 | 278 |
| 279 int32_t NewAudioConferenceMixerImpl::SetMixabilityStatus( | 279 int32_t NewAudioConferenceMixerImpl::SetMixabilityStatus( |
| 280 MixerAudioSource* audio_source, | 280 MixerAudioSource* audio_source, |
| 281 bool mixable) { | 281 bool mixable) { |
| 282 if (!mixable) { | 282 if (!mixable) { |
| 283 // Anonymous audio sources are in a separate list. Make sure that the | 283 // Anonymous audio sources are in a separate list. Make sure that the |
| 284 // audio source is in the _audioSourceList if it is being mixed. | 284 // audio source is in the _audioSourceList if it is being mixed. |
| 285 SetAnonymousMixabilityStatus(audio_source, false); | 285 SetAnonymousMixabilityStatus(audio_source, false); |
| 286 } | 286 } |
| 287 size_t numMixedAudioSources; | 287 size_t numMixedAudioSources; |
| 288 { | 288 { |
| 289 CriticalSectionScoped cs(_cbCrit.get()); | 289 CriticalSectionScoped cs(cb_crit_.get()); |
| 290 const bool isMixed = IsAudioSourceInList(*audio_source, audio_source_list_); | 290 const bool isMixed = IsAudioSourceInList(*audio_source, audio_source_list_); |
| 291 // API must be called with a new state. | 291 // API must be called with a new state. |
| 292 if (!(mixable ^ isMixed)) { | 292 if (!(mixable ^ isMixed)) { |
| 293 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, | 293 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_, |
| 294 "Mixable is aready %s", isMixed ? "ON" : "off"); | 294 "Mixable is aready %s", isMixed ? "ON" : "off"); |
| 295 return -1; | 295 return -1; |
| 296 } | 296 } |
| 297 bool success = false; | 297 bool success = false; |
| 298 if (mixable) { | 298 if (mixable) { |
| 299 success = AddAudioSourceToList(audio_source, &audio_source_list_); | 299 success = AddAudioSourceToList(audio_source, &audio_source_list_); |
| 300 } else { | 300 } else { |
| 301 success = RemoveAudioSourceFromList(audio_source, &audio_source_list_); | 301 success = RemoveAudioSourceFromList(audio_source, &audio_source_list_); |
| 302 } | 302 } |
| 303 if (!success) { | 303 if (!success) { |
| 304 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, | 304 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_, |
| 305 "failed to %s audio_source", mixable ? "add" : "remove"); | 305 "failed to %s audio_source", mixable ? "add" : "remove"); |
| 306 RTC_NOTREACHED(); | 306 RTC_NOTREACHED(); |
| 307 return -1; | 307 return -1; |
| 308 } | 308 } |
| 309 | 309 |
| 310 size_t numMixedNonAnonymous = audio_source_list_.size(); | 310 size_t numMixedNonAnonymous = audio_source_list_.size(); |
| 311 if (numMixedNonAnonymous > kMaximumAmountOfMixedAudioSources) { | 311 if (numMixedNonAnonymous > kMaximumAmountOfMixedAudioSources) { |
| 312 numMixedNonAnonymous = kMaximumAmountOfMixedAudioSources; | 312 numMixedNonAnonymous = kMaximumAmountOfMixedAudioSources; |
| 313 } | 313 } |
| 314 numMixedAudioSources = | 314 numMixedAudioSources = |
| 315 numMixedNonAnonymous + additional_audio_source_list_.size(); | 315 numMixedNonAnonymous + additional_audio_source_list_.size(); |
| 316 } | 316 } |
| 317 // A MixerAudioSource was added or removed. Make sure the scratch | 317 // A MixerAudioSource was added or removed. Make sure the scratch |
| 318 // buffer is updated if necessary. | 318 // buffer is updated if necessary. |
| 319 // Note: The scratch buffer may only be updated in Process(). | 319 // Note: The scratch buffer may only be updated in Process(). |
| 320 CriticalSectionScoped cs(_crit.get()); | 320 CriticalSectionScoped cs(crit_.get()); |
| 321 num_mixed_audio_sources_ = numMixedAudioSources; | 321 num_mixed_audio_sources_ = numMixedAudioSources; |
| 322 return 0; | 322 return 0; |
| 323 } | 323 } |
| 324 | 324 |
| 325 bool NewAudioConferenceMixerImpl::MixabilityStatus( | 325 bool NewAudioConferenceMixerImpl::MixabilityStatus( |
| 326 const MixerAudioSource& audio_source) const { | 326 const MixerAudioSource& audio_source) const { |
| 327 CriticalSectionScoped cs(_cbCrit.get()); | 327 CriticalSectionScoped cs(cb_crit_.get()); |
| 328 return IsAudioSourceInList(audio_source, audio_source_list_); | 328 return IsAudioSourceInList(audio_source, audio_source_list_); |
| 329 } | 329 } |
| 330 | 330 |
| 331 int32_t NewAudioConferenceMixerImpl::SetAnonymousMixabilityStatus( | 331 int32_t NewAudioConferenceMixerImpl::SetAnonymousMixabilityStatus( |
| 332 MixerAudioSource* audio_source, | 332 MixerAudioSource* audio_source, |
| 333 bool anonymous) { | 333 bool anonymous) { |
| 334 CriticalSectionScoped cs(_cbCrit.get()); | 334 CriticalSectionScoped cs(cb_crit_.get()); |
| 335 if (IsAudioSourceInList(*audio_source, additional_audio_source_list_)) { | 335 if (IsAudioSourceInList(*audio_source, additional_audio_source_list_)) { |
| 336 if (anonymous) { | 336 if (anonymous) { |
| 337 return 0; | 337 return 0; |
| 338 } | 338 } |
| 339 if (!RemoveAudioSourceFromList(audio_source, | 339 if (!RemoveAudioSourceFromList(audio_source, |
| 340 &additional_audio_source_list_)) { | 340 &additional_audio_source_list_)) { |
| 341 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, | 341 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_, |
| 342 "unable to remove audio_source from anonymous list"); | 342 "unable to remove audio_source from anonymous list"); |
| 343 RTC_NOTREACHED(); | 343 RTC_NOTREACHED(); |
| 344 return -1; | 344 return -1; |
| 345 } | 345 } |
| 346 return AddAudioSourceToList(audio_source, &audio_source_list_) ? 0 : -1; | 346 return AddAudioSourceToList(audio_source, &audio_source_list_) ? 0 : -1; |
| 347 } | 347 } |
| 348 if (!anonymous) { | 348 if (!anonymous) { |
| 349 return 0; | 349 return 0; |
| 350 } | 350 } |
| 351 const bool mixable = | 351 const bool mixable = |
| 352 RemoveAudioSourceFromList(audio_source, &audio_source_list_); | 352 RemoveAudioSourceFromList(audio_source, &audio_source_list_); |
| 353 if (!mixable) { | 353 if (!mixable) { |
| 354 WEBRTC_TRACE( | 354 WEBRTC_TRACE( |
| 355 kTraceWarning, kTraceAudioMixerServer, _id, | 355 kTraceWarning, kTraceAudioMixerServer, id_, |
| 356 "audio_source must be registered before turning it into anonymous"); | 356 "audio_source must be registered before turning it into anonymous"); |
| 357 // Setting anonymous status is only possible if MixerAudioSource is | 357 // Setting anonymous status is only possible if MixerAudioSource is |
| 358 // already registered. | 358 // already registered. |
| 359 return -1; | 359 return -1; |
| 360 } | 360 } |
| 361 return AddAudioSourceToList(audio_source, &additional_audio_source_list_) | 361 return AddAudioSourceToList(audio_source, &additional_audio_source_list_) |
| 362 ? 0 | 362 ? 0 |
| 363 : -1; | 363 : -1; |
| 364 } | 364 } |
| 365 | 365 |
| 366 bool NewAudioConferenceMixerImpl::AnonymousMixabilityStatus( | 366 bool NewAudioConferenceMixerImpl::AnonymousMixabilityStatus( |
| 367 const MixerAudioSource& audio_source) const { | 367 const MixerAudioSource& audio_source) const { |
| 368 CriticalSectionScoped cs(_cbCrit.get()); | 368 CriticalSectionScoped cs(cb_crit_.get()); |
| 369 return IsAudioSourceInList(audio_source, additional_audio_source_list_); | 369 return IsAudioSourceInList(audio_source, additional_audio_source_list_); |
| 370 } | 370 } |
| 371 | 371 |
| 372 AudioFrameList NewAudioConferenceMixerImpl::UpdateToMix( | 372 AudioFrameList NewAudioConferenceMixerImpl::UpdateToMix( |
| 373 size_t maxAudioFrameCounter) const { | 373 size_t maxAudioFrameCounter) const { |
| 374 AudioFrameList result; | 374 AudioFrameList result; |
| 375 std::vector<SourceFrame> audioSourceMixingDataList; | 375 std::vector<SourceFrame> audioSourceMixingDataList; |
| 376 | 376 |
| 377 // Get audio source audio and put it in the struct vector. | 377 // Get audio source audio and put it in the struct vector. |
| 378 for (MixerAudioSource* audio_source : audio_source_list_) { | 378 for (MixerAudioSource* audio_source : audio_source_list_) { |
| 379 auto audio_frame_with_info = audio_source->GetAudioFrameWithMuted( | 379 auto audio_frame_with_info = audio_source->GetAudioFrameWithMuted( |
| 380 _id, static_cast<int>(_outputFrequency)); | 380 id_, static_cast<int>(output_frequency_)); |
| 381 | 381 |
| 382 auto audio_frame_info = audio_frame_with_info.audio_frame_info; | 382 auto audio_frame_info = audio_frame_with_info.audio_frame_info; |
| 383 AudioFrame* audio_source_audio_frame = audio_frame_with_info.audio_frame; | 383 AudioFrame* audio_source_audio_frame = audio_frame_with_info.audio_frame; |
| 384 | 384 |
| 385 if (audio_frame_info == MixerAudioSource::AudioFrameInfo::kError) { | 385 if (audio_frame_info == MixerAudioSource::AudioFrameInfo::kError) { |
| 386 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, | 386 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_, |
| 387 "failed to GetAudioFrameWithMuted() from participant"); | 387 "failed to GetAudioFrameWithMuted() from participant"); |
| 388 continue; | 388 continue; |
| 389 } | 389 } |
| 390 audioSourceMixingDataList.emplace_back( | 390 audioSourceMixingDataList.emplace_back( |
| 391 audio_source, audio_source_audio_frame, | 391 audio_source, audio_source_audio_frame, |
| 392 audio_frame_info == MixerAudioSource::AudioFrameInfo::kMuted, | 392 audio_frame_info == MixerAudioSource::AudioFrameInfo::kMuted, |
| 393 audio_source->_mixHistory->WasMixed()); | 393 audio_source->_mixHistory->WasMixed()); |
| 394 } | 394 } |
| 395 | 395 |
| 396 // Sort frames by sorting function. | 396 // Sort frames by sorting function. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 422 result.emplace_back(p.audio_frame_, false); | 422 result.emplace_back(p.audio_frame_, false); |
| 423 } | 423 } |
| 424 | 424 |
| 425 p.audio_source_->_mixHistory->SetIsMixed(is_mixed); | 425 p.audio_source_->_mixHistory->SetIsMixed(is_mixed); |
| 426 } | 426 } |
| 427 return result; | 427 return result; |
| 428 } | 428 } |
| 429 | 429 |
| 430 void NewAudioConferenceMixerImpl::GetAdditionalAudio( | 430 void NewAudioConferenceMixerImpl::GetAdditionalAudio( |
| 431 AudioFrameList* additionalFramesList) const { | 431 AudioFrameList* additionalFramesList) const { |
| 432 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, | 432 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, |
| 433 "GetAdditionalAudio(additionalFramesList)"); | 433 "GetAdditionalAudio(additionalFramesList)"); |
| 434 // The GetAudioFrameWithMuted() callback may result in the audio source being | 434 // The GetAudioFrameWithMuted() callback may result in the audio source being |
| 435 // removed from additionalAudioFramesList_. If that happens it will | 435 // removed from additionalAudioFramesList_. If that happens it will |
| 436 // invalidate any iterators. Create a copy of the audio sources list such | 436 // invalidate any iterators. Create a copy of the audio sources list such |
| 437 // that the list of participants can be traversed safely. | 437 // that the list of participants can be traversed safely. |
| 438 MixerAudioSourceList additionalAudioSourceList; | 438 MixerAudioSourceList additionalAudioSourceList; |
| 439 additionalAudioSourceList.insert(additionalAudioSourceList.begin(), | 439 additionalAudioSourceList.insert(additionalAudioSourceList.begin(), |
| 440 additional_audio_source_list_.begin(), | 440 additional_audio_source_list_.begin(), |
| 441 additional_audio_source_list_.end()); | 441 additional_audio_source_list_.end()); |
| 442 | 442 |
| 443 for (MixerAudioSourceList::const_iterator audio_source = | 443 for (MixerAudioSourceList::const_iterator audio_source = |
| 444 additionalAudioSourceList.begin(); | 444 additionalAudioSourceList.begin(); |
| 445 audio_source != additionalAudioSourceList.end(); ++audio_source) { | 445 audio_source != additionalAudioSourceList.end(); ++audio_source) { |
| 446 auto audio_frame_with_info = | 446 auto audio_frame_with_info = |
| 447 (*audio_source)->GetAudioFrameWithMuted(_id, _outputFrequency); | 447 (*audio_source)->GetAudioFrameWithMuted(id_, output_frequency_); |
| 448 auto ret = audio_frame_with_info.audio_frame_info; | 448 auto ret = audio_frame_with_info.audio_frame_info; |
| 449 AudioFrame* audio_frame = audio_frame_with_info.audio_frame; | 449 AudioFrame* audio_frame = audio_frame_with_info.audio_frame; |
| 450 if (ret == MixerAudioSource::AudioFrameInfo::kError) { | 450 if (ret == MixerAudioSource::AudioFrameInfo::kError) { |
| 451 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, _id, | 451 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_, |
| 452 "failed to GetAudioFrameWithMuted() from audio_source"); | 452 "failed to GetAudioFrameWithMuted() from audio_source"); |
| 453 continue; | 453 continue; |
| 454 } | 454 } |
| 455 if (audio_frame->samples_per_channel_ == 0) { | 455 if (audio_frame->samples_per_channel_ == 0) { |
| 456 // Empty frame. Don't use it. | 456 // Empty frame. Don't use it. |
| 457 continue; | 457 continue; |
| 458 } | 458 } |
| 459 additionalFramesList->push_back(FrameAndMuteInfo( | 459 additionalFramesList->push_back(FrameAndMuteInfo( |
| 460 audio_frame, ret == MixerAudioSource::AudioFrameInfo::kMuted)); | 460 audio_frame, ret == MixerAudioSource::AudioFrameInfo::kMuted)); |
| 461 } | 461 } |
| 462 } | 462 } |
| 463 | 463 |
| 464 bool NewAudioConferenceMixerImpl::IsAudioSourceInList( | 464 bool NewAudioConferenceMixerImpl::IsAudioSourceInList( |
| 465 const MixerAudioSource& audio_source, | 465 const MixerAudioSource& audio_source, |
| 466 const MixerAudioSourceList& audioSourceList) const { | 466 const MixerAudioSourceList& audioSourceList) const { |
| 467 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, | 467 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, |
| 468 "IsAudioSourceInList(audio_source,audioSourceList)"); | 468 "IsAudioSourceInList(audio_source,audioSourceList)"); |
| 469 for (MixerAudioSourceList::const_iterator iter = audioSourceList.begin(); | 469 return std::find(audioSourceList.begin(), audioSourceList.end(), |
| 470 iter != audioSourceList.end(); ++iter) { | 470 &audio_source) != audioSourceList.end(); |
| 471 if (&audio_source == *iter) { | |
| 472 return true; | |
| 473 } | |
| 474 } | |
| 475 return false; | |
| 476 } | 471 } |
| 477 | 472 |
| 478 bool NewAudioConferenceMixerImpl::AddAudioSourceToList( | 473 bool NewAudioConferenceMixerImpl::AddAudioSourceToList( |
| 479 MixerAudioSource* audio_source, | 474 MixerAudioSource* audio_source, |
| 480 MixerAudioSourceList* audioSourceList) const { | 475 MixerAudioSourceList* audioSourceList) const { |
| 481 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, | 476 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, |
| 482 "AddAudioSourceToList(audio_source, audioSourceList)"); | 477 "AddAudioSourceToList(audio_source, audioSourceList)"); |
| 483 audioSourceList->push_back(audio_source); | 478 audioSourceList->push_back(audio_source); |
| 484 // Make sure that the mixed status is correct for new MixerAudioSource. | 479 // Make sure that the mixed status is correct for new MixerAudioSource. |
| 485 audio_source->_mixHistory->ResetMixedStatus(); | 480 audio_source->_mixHistory->ResetMixedStatus(); |
| 486 return true; | 481 return true; |
| 487 } | 482 } |
| 488 | 483 |
| 489 bool NewAudioConferenceMixerImpl::RemoveAudioSourceFromList( | 484 bool NewAudioConferenceMixerImpl::RemoveAudioSourceFromList( |
| 490 MixerAudioSource* audio_source, | 485 MixerAudioSource* audio_source, |
| 491 MixerAudioSourceList* audioSourceList) const { | 486 MixerAudioSourceList* audioSourceList) const { |
| 492 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, | 487 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, |
| 493 "RemoveAudioSourceFromList(audio_source, audioSourceList)"); | 488 "RemoveAudioSourceFromList(audio_source, audioSourceList)"); |
| 494 for (MixerAudioSourceList::iterator iter = audioSourceList->begin(); | 489 auto iter = |
| 495 iter != audioSourceList->end(); ++iter) { | 490 std::find(audioSourceList->begin(), audioSourceList->end(), audio_source); |
| 496 if (*iter == audio_source) { | 491 if (iter != audioSourceList->end()) { |
| 497 audioSourceList->erase(iter); | 492 audioSourceList->erase(iter); |
| 498 // AudioSource is no longer mixed, reset to default. | 493 // AudioSource is no longer mixed, reset to default. |
| 499 audio_source->_mixHistory->ResetMixedStatus(); | 494 audio_source->_mixHistory->ResetMixedStatus(); |
| 500 return true; | 495 return true; |
| 501 } | 496 } else { |
| 497 return false; |
| 502 } | 498 } |
| 503 return false; | |
| 504 } | 499 } |
| 505 | 500 |
| 506 int32_t NewAudioConferenceMixerImpl::MixFromList( | 501 int32_t NewAudioConferenceMixerImpl::MixFromList( |
| 507 AudioFrame* mixedAudio, | 502 AudioFrame* mixedAudio, |
| 508 const AudioFrameList& audioFrameList, | 503 const AudioFrameList& audioFrameList, |
| 509 int32_t id, | 504 int32_t id, |
| 510 bool use_limiter) { | 505 bool use_limiter) { |
| 511 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id, | 506 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id, |
| 512 "MixFromList(mixedAudio, audioFrameList)"); | 507 "MixFromList(mixedAudio, audioFrameList)"); |
| 513 if (audioFrameList.empty()) | 508 if (audioFrameList.empty()) |
| (...skipping 30 matching lines...) Expand all Loading... |
| 544 position++; | 539 position++; |
| 545 } | 540 } |
| 546 | 541 |
| 547 return 0; | 542 return 0; |
| 548 } | 543 } |
| 549 | 544 |
| 550 // TODO(andrew): consolidate this function with MixFromList. | 545 // TODO(andrew): consolidate this function with MixFromList. |
| 551 int32_t NewAudioConferenceMixerImpl::MixAnonomouslyFromList( | 546 int32_t NewAudioConferenceMixerImpl::MixAnonomouslyFromList( |
| 552 AudioFrame* mixedAudio, | 547 AudioFrame* mixedAudio, |
| 553 const AudioFrameList& audioFrameList) const { | 548 const AudioFrameList& audioFrameList) const { |
| 554 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, _id, | 549 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, |
| 555 "MixAnonomouslyFromList(mixedAudio, audioFrameList)"); | 550 "MixAnonomouslyFromList(mixedAudio, audioFrameList)"); |
| 556 | 551 |
| 557 if (audioFrameList.empty()) | 552 if (audioFrameList.empty()) |
| 558 return 0; | 553 return 0; |
| 559 | 554 |
| 560 for (AudioFrameList::const_iterator iter = audioFrameList.begin(); | 555 for (AudioFrameList::const_iterator iter = audioFrameList.begin(); |
| 561 iter != audioFrameList.end(); ++iter) { | 556 iter != audioFrameList.end(); ++iter) { |
| 562 if (!iter->muted) { | 557 if (!iter->muted) { |
| 563 MixFrames(mixedAudio, iter->frame, use_limiter_); | 558 MixFrames(mixedAudio, iter->frame, use_limiter_); |
| 564 } | 559 } |
| 565 } | 560 } |
| 566 return 0; | 561 return 0; |
| 567 } | 562 } |
| 568 | 563 |
| 569 bool NewAudioConferenceMixerImpl::LimitMixedAudio( | 564 bool NewAudioConferenceMixerImpl::LimitMixedAudio( |
| 570 AudioFrame* mixedAudio) const { | 565 AudioFrame* mixedAudio) const { |
| 571 if (!use_limiter_) { | 566 if (!use_limiter_) { |
| 572 return true; | 567 return true; |
| 573 } | 568 } |
| 574 | 569 |
| 575 // Smoothly limit the mixed frame. | 570 // Smoothly limit the mixed frame. |
| 576 const int error = _limiter->ProcessStream(mixedAudio); | 571 const int error = limiter_->ProcessStream(mixedAudio); |
| 577 | 572 |
| 578 // And now we can safely restore the level. This procedure results in | 573 // And now we can safely restore the level. This procedure results in |
| 579 // some loss of resolution, deemed acceptable. | 574 // some loss of resolution, deemed acceptable. |
| 580 // | 575 // |
| 581 // It's possible to apply the gain in the AGC (with a target level of 0 dbFS | 576 // It's possible to apply the gain in the AGC (with a target level of 0 dbFS |
| 582 // and compression gain of 6 dB). However, in the transition frame when this | 577 // and compression gain of 6 dB). However, in the transition frame when this |
| 583 // is enabled (moving from one to two audio sources) it has the potential to | 578 // is enabled (moving from one to two audio sources) it has the potential to |
| 584 // create discontinuities in the mixed frame. | 579 // create discontinuities in the mixed frame. |
| 585 // | 580 // |
| 586 // Instead we double the frame (with addition since left-shifting a | 581 // Instead we double the frame (with addition since left-shifting a |
| 587 // negative value is undefined). | 582 // negative value is undefined). |
| 588 *mixedAudio += *mixedAudio; | 583 *mixedAudio += *mixedAudio; |
| 589 | 584 |
| 590 if (error != _limiter->kNoError) { | 585 if (error != limiter_->kNoError) { |
| 591 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, _id, | 586 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_, |
| 592 "Error from AudioProcessing: %d", error); | 587 "Error from AudioProcessing: %d", error); |
| 593 RTC_NOTREACHED(); | 588 RTC_NOTREACHED(); |
| 594 return false; | 589 return false; |
| 595 } | 590 } |
| 596 return true; | 591 return true; |
| 597 } | 592 } |
| 598 } // namespace webrtc | 593 } // namespace webrtc |
| OLD | NEW |