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 |