Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(286)

Side by Side Diff: webrtc/modules/audio_mixer/audio_mixer_impl.cc

Issue 2286343002: Less lock acquisitions for AudioMixer. (Closed)
Patch Set: Rebase. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 16
17 #include "webrtc/base/thread_annotations.h"
16 #include "webrtc/modules/audio_mixer/audio_frame_manipulator.h" 18 #include "webrtc/modules/audio_mixer/audio_frame_manipulator.h"
17 #include "webrtc/modules/audio_mixer/audio_mixer_defines.h" 19 #include "webrtc/modules/audio_mixer/audio_mixer_defines.h"
18 #include "webrtc/modules/audio_processing/include/audio_processing.h" 20 #include "webrtc/modules/audio_processing/include/audio_processing.h"
19 #include "webrtc/modules/utility/include/audio_frame_operations.h" 21 #include "webrtc/modules/utility/include/audio_frame_operations.h"
20 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" 22 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
21 #include "webrtc/system_wrappers/include/trace.h" 23 #include "webrtc/system_wrappers/include/trace.h"
22 24
23 namespace webrtc { 25 namespace webrtc {
24 namespace { 26 namespace {
25 27
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 int32_t NewMixHistory::SetIsMixed(const bool mixed) { 115 int32_t NewMixHistory::SetIsMixed(const bool mixed) {
114 is_mixed_ = mixed; 116 is_mixed_ = mixed;
115 return 0; 117 return 0;
116 } 118 }
117 119
118 void NewMixHistory::ResetMixedStatus() { 120 void NewMixHistory::ResetMixedStatus() {
119 is_mixed_ = false; 121 is_mixed_ = false;
120 } 122 }
121 123
122 std::unique_ptr<AudioMixer> AudioMixer::Create(int id) { 124 std::unique_ptr<AudioMixer> AudioMixer::Create(int id) {
123 AudioMixerImpl* mixer = new AudioMixerImpl(id); 125 return AudioMixerImpl::Create(id);
124 if (!mixer->Init()) {
125 delete mixer;
126 return NULL;
127 }
128 return std::unique_ptr<AudioMixer>(mixer);
129 } 126 }
130 127
131 AudioMixerImpl::AudioMixerImpl(int id) 128 AudioMixerImpl::AudioMixerImpl(int id, std::unique_ptr<AudioProcessing> limiter)
132 : id_(id), 129 : id_(id),
133 output_frequency_(kDefaultFrequency),
134 sample_size_(0),
135 audio_source_list_(), 130 audio_source_list_(),
136 additional_audio_source_list_(), 131 additional_audio_source_list_(),
137 num_mixed_audio_sources_(0), 132 num_mixed_audio_sources_(0),
138 use_limiter_(true), 133 use_limiter_(true),
139 time_stamp_(0) { 134 time_stamp_(0),
135 limiter_(std::move(limiter)) {
136 SetOutputFrequency(kDefaultFrequency);
140 thread_checker_.DetachFromThread(); 137 thread_checker_.DetachFromThread();
141 } 138 }
142 139
143 AudioMixerImpl::~AudioMixerImpl() {} 140 AudioMixerImpl::~AudioMixerImpl() {}
144 141
145 bool AudioMixerImpl::Init() { 142 std::unique_ptr<AudioMixer> AudioMixerImpl::Create(int id) {
146 crit_.reset(CriticalSectionWrapper::CreateCriticalSection());
147 if (crit_.get() == NULL)
148 return false;
149
150 cb_crit_.reset(CriticalSectionWrapper::CreateCriticalSection());
151 if (cb_crit_.get() == NULL)
152 return false;
153
154 Config config; 143 Config config;
155 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); 144 config.Set<ExperimentalAgc>(new ExperimentalAgc(false));
156 limiter_.reset(AudioProcessing::Create(config)); 145 std::unique_ptr<AudioProcessing> limiter(AudioProcessing::Create(config));
157 if (!limiter_.get()) 146 if (!limiter.get())
158 return false; 147 return nullptr;
159 148
160 if (SetOutputFrequency(kDefaultFrequency) == -1) 149 if (limiter->gain_control()->set_mode(GainControl::kFixedDigital) !=
161 return false; 150 limiter->kNoError)
162 151 return nullptr;
163 if (limiter_->gain_control()->set_mode(GainControl::kFixedDigital) !=
164 limiter_->kNoError)
165 return false;
166 152
167 // We smoothly limit the mixed frame to -7 dbFS. -6 would correspond to the 153 // 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 154 // divide-by-2 but -7 is used instead to give a bit of headroom since the
169 // AGC is not a hard limiter. 155 // AGC is not a hard limiter.
170 if (limiter_->gain_control()->set_target_level_dbfs(7) != limiter_->kNoError) 156 if (limiter->gain_control()->set_target_level_dbfs(7) != limiter->kNoError)
171 return false; 157 return nullptr;
172 158
173 if (limiter_->gain_control()->set_compression_gain_db(0) != 159 if (limiter->gain_control()->set_compression_gain_db(0) != limiter->kNoError)
174 limiter_->kNoError) 160 return nullptr;
175 return false;
176 161
177 if (limiter_->gain_control()->enable_limiter(true) != limiter_->kNoError) 162 if (limiter->gain_control()->enable_limiter(true) != limiter->kNoError)
178 return false; 163 return nullptr;
179 164
180 if (limiter_->gain_control()->Enable(true) != limiter_->kNoError) 165 if (limiter->gain_control()->Enable(true) != limiter->kNoError)
181 return false; 166 return nullptr;
182 167
183 return true; 168 return std::unique_ptr<AudioMixer>(
169 new AudioMixerImpl(id, std::move(limiter)));
184 } 170 }
185 171
186 void AudioMixerImpl::Mix(int sample_rate, 172 void AudioMixerImpl::Mix(int sample_rate,
187 size_t number_of_channels, 173 size_t number_of_channels,
188 AudioFrame* audio_frame_for_mixing) { 174 AudioFrame* audio_frame_for_mixing) {
189 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); 175 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2);
190 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 176 RTC_DCHECK_RUN_ON(&thread_checker_);
177 std::map<int, MixerAudioSource*> mixedAudioSourcesMap;
178
179 if (sample_rate != kNbInHz && sample_rate != kWbInHz &&
180 sample_rate != kSwbInHz && sample_rate != kFbInHz) {
181 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_,
182 "Invalid frequency: %d", sample_rate);
183 RTC_NOTREACHED();
184 return;
185 }
186
187 if (OutputFrequency() != sample_rate) {
188 SetOutputFrequency(static_cast<Frequency>(sample_rate));
189 }
190
191 AudioFrameList mixList; 191 AudioFrameList mixList;
192 AudioFrameList additionalFramesList; 192 AudioFrameList additionalFramesList;
193 std::map<int, MixerAudioSource*> mixedAudioSourcesMap; 193 int num_mixed_audio_sources;
194 { 194 {
195 CriticalSectionScoped cs(cb_crit_.get()); 195 rtc::CritScope lock(&crit_);
196 Frequency mixing_frequency;
197
198 switch (sample_rate) {
199 case 8000:
200 mixing_frequency = kNbInHz;
201 break;
202 case 16000:
203 mixing_frequency = kWbInHz;
204 break;
205 case 32000:
206 mixing_frequency = kSwbInHz;
207 break;
208 case 48000:
209 mixing_frequency = kFbInHz;
210 break;
211 default:
212 RTC_NOTREACHED();
213 return;
214 }
215
216 if (OutputFrequency() != mixing_frequency) {
217 SetOutputFrequency(mixing_frequency);
218 }
219
220 mixList = UpdateToMix(kMaximumAmountOfMixedAudioSources); 196 mixList = UpdateToMix(kMaximumAmountOfMixedAudioSources);
221 GetAdditionalAudio(&additionalFramesList); 197 GetAdditionalAudio(&additionalFramesList);
198 num_mixed_audio_sources = static_cast<int>(num_mixed_audio_sources_);
222 } 199 }
223 200
224 for (FrameAndMuteInfo& frame_and_mute : mixList) { 201 for (FrameAndMuteInfo& frame_and_mute : mixList) {
225 RemixFrame(frame_and_mute.frame, number_of_channels); 202 RemixFrame(frame_and_mute.frame, number_of_channels);
226 } 203 }
227 for (FrameAndMuteInfo& frame_and_mute : additionalFramesList) { 204 for (FrameAndMuteInfo& frame_and_mute : additionalFramesList) {
228 RemixFrame(frame_and_mute.frame, number_of_channels); 205 RemixFrame(frame_and_mute.frame, number_of_channels);
229 } 206 }
230 207
231 audio_frame_for_mixing->UpdateFrame( 208 audio_frame_for_mixing->UpdateFrame(
232 -1, time_stamp_, NULL, 0, output_frequency_, AudioFrame::kNormalSpeech, 209 -1, time_stamp_, NULL, 0, output_frequency_, AudioFrame::kNormalSpeech,
233 AudioFrame::kVadPassive, number_of_channels); 210 AudioFrame::kVadPassive, number_of_channels);
234 211
235 time_stamp_ += static_cast<uint32_t>(sample_size_); 212 time_stamp_ += static_cast<uint32_t>(sample_size_);
236 213
237 use_limiter_ = num_mixed_audio_sources_ > 1; 214 use_limiter_ = num_mixed_audio_sources > 1;
238 215
239 // We only use the limiter if it supports the output sample rate and 216 // We only use the limiter if it supports the output sample rate and
240 // we're actually mixing multiple streams. 217 // we're actually mixing multiple streams.
241 MixFromList(audio_frame_for_mixing, mixList, id_, use_limiter_); 218 MixFromList(audio_frame_for_mixing, mixList, id_, use_limiter_);
242 219 MixAnonomouslyFromList(audio_frame_for_mixing, additionalFramesList);
243 { 220 if (audio_frame_for_mixing->samples_per_channel_ == 0) {
244 CriticalSectionScoped cs(crit_.get()); 221 // Nothing was mixed, set the audio samples to silence.
245 MixAnonomouslyFromList(audio_frame_for_mixing, additionalFramesList); 222 audio_frame_for_mixing->samples_per_channel_ = sample_size_;
246 223 audio_frame_for_mixing->Mute();
247 if (audio_frame_for_mixing->samples_per_channel_ == 0) { 224 } else {
248 // Nothing was mixed, set the audio samples to silence. 225 // Only call the limiter if we have something to mix.
249 audio_frame_for_mixing->samples_per_channel_ = sample_size_; 226 LimitMixedAudio(audio_frame_for_mixing);
250 audio_frame_for_mixing->Mute();
251 } else {
252 // Only call the limiter if we have something to mix.
253 LimitMixedAudio(audio_frame_for_mixing);
254 }
255 } 227 }
256 228
257 // Pass the final result to the level indicator. 229 // Pass the final result to the level indicator.
258 audio_level_.ComputeLevel(*audio_frame_for_mixing); 230 audio_level_.ComputeLevel(*audio_frame_for_mixing);
259 231
260 return; 232 return;
261 } 233 }
262 234
263 int32_t AudioMixerImpl::SetOutputFrequency(const Frequency& frequency) { 235 int32_t AudioMixerImpl::SetOutputFrequency(const Frequency& frequency) {
264 CriticalSectionScoped cs(crit_.get()); 236 RTC_DCHECK_RUN_ON(&thread_checker_);
265
266 output_frequency_ = frequency; 237 output_frequency_ = frequency;
267 sample_size_ = 238 sample_size_ =
268 static_cast<size_t>((output_frequency_ * kFrameDurationInMs) / 1000); 239 static_cast<size_t>((output_frequency_ * kFrameDurationInMs) / 1000);
269 240
270 return 0; 241 return 0;
271 } 242 }
272 243
273 AudioMixer::Frequency AudioMixerImpl::OutputFrequency() const { 244 AudioMixer::Frequency AudioMixerImpl::OutputFrequency() const {
274 CriticalSectionScoped cs(crit_.get()); 245 RTC_DCHECK_RUN_ON(&thread_checker_);
275 return output_frequency_; 246 return output_frequency_;
276 } 247 }
277 248
278 int32_t AudioMixerImpl::SetMixabilityStatus(MixerAudioSource* audio_source, 249 int32_t AudioMixerImpl::SetMixabilityStatus(MixerAudioSource* audio_source,
279 bool mixable) { 250 bool mixable) {
280 if (!mixable) { 251 if (!mixable) {
281 // Anonymous audio sources are in a separate list. Make sure that the 252 // Anonymous audio sources are in a separate list. Make sure that the
282 // audio source is in the _audioSourceList if it is being mixed. 253 // audio source is in the _audioSourceList if it is being mixed.
283 SetAnonymousMixabilityStatus(audio_source, false); 254 SetAnonymousMixabilityStatus(audio_source, false);
284 } 255 }
285 size_t numMixedAudioSources;
286 { 256 {
287 CriticalSectionScoped cs(cb_crit_.get()); 257 rtc::CritScope lock(&crit_);
288 const bool isMixed = IsAudioSourceInList(*audio_source, audio_source_list_); 258 const bool isMixed = IsAudioSourceInList(*audio_source, audio_source_list_);
289 // API must be called with a new state. 259 // API must be called with a new state.
290 if (!(mixable ^ isMixed)) { 260 if (!(mixable ^ isMixed)) {
291 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_, 261 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_,
292 "Mixable is aready %s", isMixed ? "ON" : "off"); 262 "Mixable is aready %s", isMixed ? "ON" : "off");
293 return -1; 263 return -1;
294 } 264 }
295 bool success = false; 265 bool success = false;
296 if (mixable) { 266 if (mixable) {
297 success = AddAudioSourceToList(audio_source, &audio_source_list_); 267 success = AddAudioSourceToList(audio_source, &audio_source_list_);
298 } else { 268 } else {
299 success = RemoveAudioSourceFromList(audio_source, &audio_source_list_); 269 success = RemoveAudioSourceFromList(audio_source, &audio_source_list_);
300 } 270 }
301 if (!success) { 271 if (!success) {
302 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_, 272 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_,
303 "failed to %s audio_source", mixable ? "add" : "remove"); 273 "failed to %s audio_source", mixable ? "add" : "remove");
304 RTC_NOTREACHED(); 274 RTC_NOTREACHED();
305 return -1; 275 return -1;
306 } 276 }
307 277
308 size_t numMixedNonAnonymous = audio_source_list_.size(); 278 size_t numMixedNonAnonymous = audio_source_list_.size();
309 if (numMixedNonAnonymous > kMaximumAmountOfMixedAudioSources) { 279 if (numMixedNonAnonymous > kMaximumAmountOfMixedAudioSources) {
310 numMixedNonAnonymous = kMaximumAmountOfMixedAudioSources; 280 numMixedNonAnonymous = kMaximumAmountOfMixedAudioSources;
311 } 281 }
312 numMixedAudioSources = 282 num_mixed_audio_sources_ =
313 numMixedNonAnonymous + additional_audio_source_list_.size(); 283 numMixedNonAnonymous + additional_audio_source_list_.size();
314 } 284 }
315 // A MixerAudioSource was added or removed. Make sure the scratch
316 // buffer is updated if necessary.
317 // Note: The scratch buffer may only be updated in Process().
318 CriticalSectionScoped cs(crit_.get());
319 num_mixed_audio_sources_ = numMixedAudioSources;
320 return 0; 285 return 0;
321 } 286 }
322 287
323 bool AudioMixerImpl::MixabilityStatus( 288 bool AudioMixerImpl::MixabilityStatus(
324 const MixerAudioSource& audio_source) const { 289 const MixerAudioSource& audio_source) const {
325 CriticalSectionScoped cs(cb_crit_.get()); 290 rtc::CritScope lock(&crit_);
326 return IsAudioSourceInList(audio_source, audio_source_list_); 291 return IsAudioSourceInList(audio_source, audio_source_list_);
327 } 292 }
328 293
329 int32_t AudioMixerImpl::SetAnonymousMixabilityStatus( 294 int32_t AudioMixerImpl::SetAnonymousMixabilityStatus(
330 MixerAudioSource* audio_source, 295 MixerAudioSource* audio_source,
331 bool anonymous) { 296 bool anonymous) {
332 CriticalSectionScoped cs(cb_crit_.get()); 297 rtc::CritScope lock(&crit_);
333 if (IsAudioSourceInList(*audio_source, additional_audio_source_list_)) { 298 if (IsAudioSourceInList(*audio_source, additional_audio_source_list_)) {
334 if (anonymous) { 299 if (anonymous) {
335 return 0; 300 return 0;
336 } 301 }
337 if (!RemoveAudioSourceFromList(audio_source, 302 if (!RemoveAudioSourceFromList(audio_source,
338 &additional_audio_source_list_)) { 303 &additional_audio_source_list_)) {
339 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_, 304 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_,
340 "unable to remove audio_source from anonymous list"); 305 "unable to remove audio_source from anonymous list");
341 RTC_NOTREACHED(); 306 RTC_NOTREACHED();
342 return -1; 307 return -1;
(...skipping 13 matching lines...) Expand all
356 // already registered. 321 // already registered.
357 return -1; 322 return -1;
358 } 323 }
359 return AddAudioSourceToList(audio_source, &additional_audio_source_list_) 324 return AddAudioSourceToList(audio_source, &additional_audio_source_list_)
360 ? 0 325 ? 0
361 : -1; 326 : -1;
362 } 327 }
363 328
364 bool AudioMixerImpl::AnonymousMixabilityStatus( 329 bool AudioMixerImpl::AnonymousMixabilityStatus(
365 const MixerAudioSource& audio_source) const { 330 const MixerAudioSource& audio_source) const {
366 CriticalSectionScoped cs(cb_crit_.get()); 331 rtc::CritScope lock(&crit_);
367 return IsAudioSourceInList(audio_source, additional_audio_source_list_); 332 return IsAudioSourceInList(audio_source, additional_audio_source_list_);
368 } 333 }
369 334
370 AudioFrameList AudioMixerImpl::UpdateToMix(size_t maxAudioFrameCounter) const { 335 AudioFrameList AudioMixerImpl::UpdateToMix(size_t maxAudioFrameCounter) const {
336 RTC_DCHECK_RUN_ON(&thread_checker_);
371 AudioFrameList result; 337 AudioFrameList result;
372 std::vector<SourceFrame> audioSourceMixingDataList; 338 std::vector<SourceFrame> audioSourceMixingDataList;
373 339
374 // Get audio source audio and put it in the struct vector. 340 // Get audio source audio and put it in the struct vector.
375 for (MixerAudioSource* audio_source : audio_source_list_) { 341 for (MixerAudioSource* audio_source : audio_source_list_) {
376 auto audio_frame_with_info = audio_source->GetAudioFrameWithMuted( 342 auto audio_frame_with_info = audio_source->GetAudioFrameWithMuted(
377 id_, static_cast<int>(output_frequency_)); 343 id_, static_cast<int>(output_frequency_));
378 344
379 auto audio_frame_info = audio_frame_with_info.audio_frame_info; 345 auto audio_frame_info = audio_frame_with_info.audio_frame_info;
380 AudioFrame* audio_source_audio_frame = audio_frame_with_info.audio_frame; 346 AudioFrame* audio_source_audio_frame = audio_frame_with_info.audio_frame;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
419 result.emplace_back(p.audio_frame_, false); 385 result.emplace_back(p.audio_frame_, false);
420 } 386 }
421 387
422 p.audio_source_->_mixHistory->SetIsMixed(is_mixed); 388 p.audio_source_->_mixHistory->SetIsMixed(is_mixed);
423 } 389 }
424 return result; 390 return result;
425 } 391 }
426 392
427 void AudioMixerImpl::GetAdditionalAudio( 393 void AudioMixerImpl::GetAdditionalAudio(
428 AudioFrameList* additionalFramesList) const { 394 AudioFrameList* additionalFramesList) const {
395 RTC_DCHECK_RUN_ON(&thread_checker_);
429 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, 396 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
430 "GetAdditionalAudio(additionalFramesList)"); 397 "GetAdditionalAudio(additionalFramesList)");
431 // The GetAudioFrameWithMuted() callback may result in the audio source being 398 // The GetAudioFrameWithMuted() callback may result in the audio source being
432 // removed from additionalAudioFramesList_. If that happens it will 399 // removed from additionalAudioFramesList_. If that happens it will
433 // invalidate any iterators. Create a copy of the audio sources list such 400 // invalidate any iterators. Create a copy of the audio sources list such
434 // that the list of participants can be traversed safely. 401 // that the list of participants can be traversed safely.
435 MixerAudioSourceList additionalAudioSourceList; 402 MixerAudioSourceList additionalAudioSourceList;
436 additionalAudioSourceList.insert(additionalAudioSourceList.begin(), 403 additionalAudioSourceList.insert(additionalAudioSourceList.begin(),
437 additional_audio_source_list_.begin(), 404 additional_audio_source_list_.begin(),
438 additional_audio_source_list_.end()); 405 additional_audio_source_list_.end());
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
526 position++; 493 position++;
527 } 494 }
528 495
529 return 0; 496 return 0;
530 } 497 }
531 498
532 // TODO(andrew): consolidate this function with MixFromList. 499 // TODO(andrew): consolidate this function with MixFromList.
533 int32_t AudioMixerImpl::MixAnonomouslyFromList( 500 int32_t AudioMixerImpl::MixAnonomouslyFromList(
534 AudioFrame* mixedAudio, 501 AudioFrame* mixedAudio,
535 const AudioFrameList& audioFrameList) const { 502 const AudioFrameList& audioFrameList) const {
503 RTC_DCHECK_RUN_ON(&thread_checker_);
536 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_, 504 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
537 "MixAnonomouslyFromList(mixedAudio, audioFrameList)"); 505 "MixAnonomouslyFromList(mixedAudio, audioFrameList)");
538 506
539 if (audioFrameList.empty()) 507 if (audioFrameList.empty())
540 return 0; 508 return 0;
541 509
542 for (AudioFrameList::const_iterator iter = audioFrameList.begin(); 510 for (AudioFrameList::const_iterator iter = audioFrameList.begin();
543 iter != audioFrameList.end(); ++iter) { 511 iter != audioFrameList.end(); ++iter) {
544 if (!iter->muted) { 512 if (!iter->muted) {
545 MixFrames(mixedAudio, iter->frame, use_limiter_); 513 MixFrames(mixedAudio, iter->frame, use_limiter_);
546 } 514 }
547 } 515 }
548 return 0; 516 return 0;
549 } 517 }
550 518
551 bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixedAudio) const { 519 bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixedAudio) const {
520 RTC_DCHECK_RUN_ON(&thread_checker_);
552 if (!use_limiter_) { 521 if (!use_limiter_) {
553 return true; 522 return true;
554 } 523 }
555 524
556 // Smoothly limit the mixed frame. 525 // Smoothly limit the mixed frame.
557 const int error = limiter_->ProcessStream(mixedAudio); 526 const int error = limiter_->ProcessStream(mixedAudio);
558 527
559 // And now we can safely restore the level. This procedure results in 528 // And now we can safely restore the level. This procedure results in
560 // some loss of resolution, deemed acceptable. 529 // some loss of resolution, deemed acceptable.
561 // 530 //
562 // It's possible to apply the gain in the AGC (with a target level of 0 dbFS 531 // It's possible to apply the gain in the AGC (with a target level of 0 dbFS
563 // and compression gain of 6 dB). However, in the transition frame when this 532 // and compression gain of 6 dB). However, in the transition frame when this
564 // is enabled (moving from one to two audio sources) it has the potential to 533 // is enabled (moving from one to two audio sources) it has the potential to
565 // create discontinuities in the mixed frame. 534 // create discontinuities in the mixed frame.
566 // 535 //
567 // Instead we double the frame (with addition since left-shifting a 536 // Instead we double the frame (with addition since left-shifting a
568 // negative value is undefined). 537 // negative value is undefined).
569 *mixedAudio += *mixedAudio; 538 *mixedAudio += *mixedAudio;
570 539
571 if (error != limiter_->kNoError) { 540 if (error != limiter_->kNoError) {
572 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_, 541 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_,
573 "Error from AudioProcessing: %d", error); 542 "Error from AudioProcessing: %d", error);
574 RTC_NOTREACHED(); 543 RTC_NOTREACHED();
575 return false; 544 return false;
576 } 545 }
577 return true; 546 return true;
578 } 547 }
579 548
580 int AudioMixerImpl::GetOutputAudioLevel() { 549 int AudioMixerImpl::GetOutputAudioLevel() {
550 RTC_DCHECK_RUN_ON(&thread_checker_);
581 const int level = audio_level_.Level(); 551 const int level = audio_level_.Level();
582 WEBRTC_TRACE(kTraceStateInfo, kTraceAudioMixerServer, id_, 552 WEBRTC_TRACE(kTraceStateInfo, kTraceAudioMixerServer, id_,
583 "GetAudioOutputLevel() => level=%d", level); 553 "GetAudioOutputLevel() => level=%d", level);
584 return level; 554 return level;
585 } 555 }
586 556
587 int AudioMixerImpl::GetOutputAudioLevelFullRange() { 557 int AudioMixerImpl::GetOutputAudioLevelFullRange() {
558 RTC_DCHECK_RUN_ON(&thread_checker_);
588 const int level = audio_level_.LevelFullRange(); 559 const int level = audio_level_.LevelFullRange();
589 WEBRTC_TRACE(kTraceStateInfo, kTraceAudioMixerServer, id_, 560 WEBRTC_TRACE(kTraceStateInfo, kTraceAudioMixerServer, id_,
590 "GetAudioOutputLevelFullRange() => level=%d", level); 561 "GetAudioOutputLevelFullRange() => level=%d", level);
591 return level; 562 return level;
592 } 563 }
593 } // namespace webrtc 564 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/audio_mixer/audio_mixer_impl.h ('k') | webrtc/modules/audio_mixer/test/audio_mixer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698