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

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

Issue 2286343002: Less lock acquisitions for AudioMixer. (Closed)
Patch Set: GUARDED_BY, ACCESS_ON, C header and EXPECT_EQ order. 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 15
16 #include "webrtc/base/thread_annotations.h"
16 #include "webrtc/modules/audio_mixer/audio_frame_manipulator.h" 17 #include "webrtc/modules/audio_mixer/audio_frame_manipulator.h"
17 #include "webrtc/modules/audio_mixer/audio_mixer_defines.h" 18 #include "webrtc/modules/audio_mixer/audio_mixer_defines.h"
18 #include "webrtc/modules/audio_processing/include/audio_processing.h" 19 #include "webrtc/modules/audio_processing/include/audio_processing.h"
19 #include "webrtc/modules/utility/include/audio_frame_operations.h" 20 #include "webrtc/modules/utility/include/audio_frame_operations.h"
20 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" 21 #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
21 #include "webrtc/system_wrappers/include/trace.h" 22 #include "webrtc/system_wrappers/include/trace.h"
22 23
23 namespace webrtc { 24 namespace webrtc {
24 namespace { 25 namespace {
25 26
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
140 thread_checker_.DetachFromThread(); 141 thread_checker_.DetachFromThread();
141 } 142 }
142 143
143 AudioMixerImpl::~AudioMixerImpl() {} 144 AudioMixerImpl::~AudioMixerImpl() {}
144 145
145 bool AudioMixerImpl::Init() { 146 bool AudioMixerImpl::Init() {
146 crit_.reset(CriticalSectionWrapper::CreateCriticalSection()); 147 crit_.reset(CriticalSectionWrapper::CreateCriticalSection());
147 if (crit_.get() == NULL) 148 if (crit_.get() == NULL)
148 return false; 149 return false;
149 150
150 cb_crit_.reset(CriticalSectionWrapper::CreateCriticalSection());
151 if (cb_crit_.get() == NULL)
152 return false;
153
154 Config config; 151 Config config;
155 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); 152 config.Set<ExperimentalAgc>(new ExperimentalAgc(false));
156 limiter_.reset(AudioProcessing::Create(config)); 153 limiter_.reset(AudioProcessing::Create(config));
157 if (!limiter_.get()) 154 if (!limiter_.get())
158 return false; 155 return false;
159 156
160 if (SetOutputFrequency(kDefaultFrequency) == -1) 157 if (SetOutputFrequency(kDefaultFrequency) == -1)
161 return false; 158 return false;
162 159
163 if (limiter_->gain_control()->set_mode(GainControl::kFixedDigital) != 160 if (limiter_->gain_control()->set_mode(GainControl::kFixedDigital) !=
(...skipping 17 matching lines...) Expand all
181 return false; 178 return false;
182 179
183 return true; 180 return true;
184 } 181 }
185 182
186 void AudioMixerImpl::Mix(int sample_rate, 183 void AudioMixerImpl::Mix(int sample_rate,
187 size_t number_of_channels, 184 size_t number_of_channels,
188 AudioFrame* audio_frame_for_mixing) { 185 AudioFrame* audio_frame_for_mixing) {
189 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); 186 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2);
190 RTC_DCHECK(thread_checker_.CalledOnValidThread()); 187 RTC_DCHECK(thread_checker_.CalledOnValidThread());
188 std::map<int, MixerAudioSource*> mixedAudioSourcesMap;
189
190 if (sample_rate != kNbInHz && sample_rate != kWbInHz &&
191 sample_rate != kSwbInHz && sample_rate != kFbInHz) {
192 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_,
193 "Invalid frequency: %d", sample_rate);
194 RTC_NOTREACHED();
195 return;
196 }
197
198 if (OutputFrequency() != sample_rate) {
199 SetOutputFrequency(static_cast<Frequency>(sample_rate));
200 }
201
191 AudioFrameList mixList; 202 AudioFrameList mixList;
192 AudioFrameList additionalFramesList; 203 AudioFrameList additionalFramesList;
193 std::map<int, MixerAudioSource*> mixedAudioSourcesMap; 204 int num_mixed_audio_sources;
194 { 205 {
195 CriticalSectionScoped cs(cb_crit_.get()); 206 CriticalSectionScoped cs(crit_.get());
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); 207 mixList = UpdateToMix(kMaximumAmountOfMixedAudioSources);
221 GetAdditionalAudio(&additionalFramesList); 208 GetAdditionalAudio(&additionalFramesList);
209 num_mixed_audio_sources = num_mixed_audio_sources_;
222 } 210 }
223 211
224 for (FrameAndMuteInfo& frame_and_mute : mixList) { 212 for (FrameAndMuteInfo& frame_and_mute : mixList) {
225 RemixFrame(frame_and_mute.frame, number_of_channels); 213 RemixFrame(frame_and_mute.frame, number_of_channels);
226 } 214 }
227 for (FrameAndMuteInfo& frame_and_mute : additionalFramesList) { 215 for (FrameAndMuteInfo& frame_and_mute : additionalFramesList) {
228 RemixFrame(frame_and_mute.frame, number_of_channels); 216 RemixFrame(frame_and_mute.frame, number_of_channels);
229 } 217 }
230 218
231 audio_frame_for_mixing->UpdateFrame( 219 audio_frame_for_mixing->UpdateFrame(
232 -1, time_stamp_, NULL, 0, output_frequency_, AudioFrame::kNormalSpeech, 220 -1, time_stamp_, NULL, 0, output_frequency_, AudioFrame::kNormalSpeech,
233 AudioFrame::kVadPassive, number_of_channels); 221 AudioFrame::kVadPassive, number_of_channels);
234 222
235 time_stamp_ += static_cast<uint32_t>(sample_size_); 223 time_stamp_ += static_cast<uint32_t>(sample_size_);
236 224
237 use_limiter_ = num_mixed_audio_sources_ > 1; 225 use_limiter_ = num_mixed_audio_sources > 1;
238 226
239 // We only use the limiter if it supports the output sample rate and 227 // We only use the limiter if it supports the output sample rate and
240 // we're actually mixing multiple streams. 228 // we're actually mixing multiple streams.
241 MixFromList(audio_frame_for_mixing, mixList, id_, use_limiter_); 229 MixFromList(audio_frame_for_mixing, mixList, id_, use_limiter_);
242 230 MixAnonomouslyFromList(audio_frame_for_mixing, additionalFramesList);
243 { 231 if (audio_frame_for_mixing->samples_per_channel_ == 0) {
244 CriticalSectionScoped cs(crit_.get()); 232 // Nothing was mixed, set the audio samples to silence.
245 MixAnonomouslyFromList(audio_frame_for_mixing, additionalFramesList); 233 audio_frame_for_mixing->samples_per_channel_ = sample_size_;
246 234 audio_frame_for_mixing->Mute();
247 if (audio_frame_for_mixing->samples_per_channel_ == 0) { 235 } else {
248 // Nothing was mixed, set the audio samples to silence. 236 // Only call the limiter if we have something to mix.
249 audio_frame_for_mixing->samples_per_channel_ = sample_size_; 237 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 } 238 }
256 239
257 // Pass the final result to the level indicator. 240 // Pass the final result to the level indicator.
258 audio_level_.ComputeLevel(*audio_frame_for_mixing); 241 audio_level_.ComputeLevel(*audio_frame_for_mixing);
259 242
260 return; 243 return;
261 } 244 }
262 245
263 int32_t AudioMixerImpl::SetOutputFrequency(const Frequency& frequency) { 246 int32_t AudioMixerImpl::SetOutputFrequency(const Frequency& frequency) {
264 CriticalSectionScoped cs(crit_.get()); 247 RTC_DCHECK(thread_checker_.CalledOnValidThread());
265
266 output_frequency_ = frequency; 248 output_frequency_ = frequency;
267 sample_size_ = 249 sample_size_ =
268 static_cast<size_t>((output_frequency_ * kFrameDurationInMs) / 1000); 250 static_cast<size_t>((output_frequency_ * kFrameDurationInMs) / 1000);
269 251
270 return 0; 252 return 0;
271 } 253 }
272 254
273 AudioMixer::Frequency AudioMixerImpl::OutputFrequency() const { 255 AudioMixer::Frequency AudioMixerImpl::OutputFrequency() const {
274 CriticalSectionScoped cs(crit_.get()); 256 RTC_DCHECK(thread_checker_.CalledOnValidThread());
275 return output_frequency_; 257 return output_frequency_;
276 } 258 }
277 259
278 int32_t AudioMixerImpl::SetMixabilityStatus(MixerAudioSource* audio_source, 260 int32_t AudioMixerImpl::SetMixabilityStatus(MixerAudioSource* audio_source,
279 bool mixable) { 261 bool mixable) {
280 if (!mixable) { 262 if (!mixable) {
281 // Anonymous audio sources are in a separate list. Make sure that the 263 // Anonymous audio sources are in a separate list. Make sure that the
282 // audio source is in the _audioSourceList if it is being mixed. 264 // audio source is in the _audioSourceList if it is being mixed.
283 SetAnonymousMixabilityStatus(audio_source, false); 265 SetAnonymousMixabilityStatus(audio_source, false);
284 } 266 }
285 size_t numMixedAudioSources;
286 { 267 {
287 CriticalSectionScoped cs(cb_crit_.get()); 268 CriticalSectionScoped cs(crit_.get());
288 const bool isMixed = IsAudioSourceInList(*audio_source, audio_source_list_); 269 const bool isMixed = IsAudioSourceInList(*audio_source, audio_source_list_);
289 // API must be called with a new state. 270 // API must be called with a new state.
290 if (!(mixable ^ isMixed)) { 271 if (!(mixable ^ isMixed)) {
291 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_, 272 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_,
292 "Mixable is aready %s", isMixed ? "ON" : "off"); 273 "Mixable is aready %s", isMixed ? "ON" : "off");
293 return -1; 274 return -1;
294 } 275 }
295 bool success = false; 276 bool success = false;
296 if (mixable) { 277 if (mixable) {
297 success = AddAudioSourceToList(audio_source, &audio_source_list_); 278 success = AddAudioSourceToList(audio_source, &audio_source_list_);
298 } else { 279 } else {
299 success = RemoveAudioSourceFromList(audio_source, &audio_source_list_); 280 success = RemoveAudioSourceFromList(audio_source, &audio_source_list_);
300 } 281 }
301 if (!success) { 282 if (!success) {
302 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_, 283 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_,
303 "failed to %s audio_source", mixable ? "add" : "remove"); 284 "failed to %s audio_source", mixable ? "add" : "remove");
304 RTC_NOTREACHED(); 285 RTC_NOTREACHED();
305 return -1; 286 return -1;
306 } 287 }
307 288
308 size_t numMixedNonAnonymous = audio_source_list_.size(); 289 size_t numMixedNonAnonymous = audio_source_list_.size();
309 if (numMixedNonAnonymous > kMaximumAmountOfMixedAudioSources) { 290 if (numMixedNonAnonymous > kMaximumAmountOfMixedAudioSources) {
310 numMixedNonAnonymous = kMaximumAmountOfMixedAudioSources; 291 numMixedNonAnonymous = kMaximumAmountOfMixedAudioSources;
311 } 292 }
312 numMixedAudioSources = 293 num_mixed_audio_sources_ =
313 numMixedNonAnonymous + additional_audio_source_list_.size(); 294 numMixedNonAnonymous + additional_audio_source_list_.size();
314 } 295 }
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; 296 return 0;
321 } 297 }
322 298
323 bool AudioMixerImpl::MixabilityStatus( 299 bool AudioMixerImpl::MixabilityStatus(
324 const MixerAudioSource& audio_source) const { 300 const MixerAudioSource& audio_source) const {
325 CriticalSectionScoped cs(cb_crit_.get()); 301 CriticalSectionScoped cs(crit_.get());
326 return IsAudioSourceInList(audio_source, audio_source_list_); 302 return IsAudioSourceInList(audio_source, audio_source_list_);
327 } 303 }
328 304
329 int32_t AudioMixerImpl::SetAnonymousMixabilityStatus( 305 int32_t AudioMixerImpl::SetAnonymousMixabilityStatus(
330 MixerAudioSource* audio_source, 306 MixerAudioSource* audio_source,
331 bool anonymous) { 307 bool anonymous) {
332 CriticalSectionScoped cs(cb_crit_.get()); 308 CriticalSectionScoped cs(crit_.get());
333 if (IsAudioSourceInList(*audio_source, additional_audio_source_list_)) { 309 if (IsAudioSourceInList(*audio_source, additional_audio_source_list_)) {
334 if (anonymous) { 310 if (anonymous) {
335 return 0; 311 return 0;
336 } 312 }
337 if (!RemoveAudioSourceFromList(audio_source, 313 if (!RemoveAudioSourceFromList(audio_source,
338 &additional_audio_source_list_)) { 314 &additional_audio_source_list_)) {
339 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_, 315 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_,
340 "unable to remove audio_source from anonymous list"); 316 "unable to remove audio_source from anonymous list");
341 RTC_NOTREACHED(); 317 RTC_NOTREACHED();
342 return -1; 318 return -1;
(...skipping 13 matching lines...) Expand all
356 // already registered. 332 // already registered.
357 return -1; 333 return -1;
358 } 334 }
359 return AddAudioSourceToList(audio_source, &additional_audio_source_list_) 335 return AddAudioSourceToList(audio_source, &additional_audio_source_list_)
360 ? 0 336 ? 0
361 : -1; 337 : -1;
362 } 338 }
363 339
364 bool AudioMixerImpl::AnonymousMixabilityStatus( 340 bool AudioMixerImpl::AnonymousMixabilityStatus(
365 const MixerAudioSource& audio_source) const { 341 const MixerAudioSource& audio_source) const {
366 CriticalSectionScoped cs(cb_crit_.get()); 342 CriticalSectionScoped cs(crit_.get());
367 return IsAudioSourceInList(audio_source, additional_audio_source_list_); 343 return IsAudioSourceInList(audio_source, additional_audio_source_list_);
368 } 344 }
369 345
370 AudioFrameList AudioMixerImpl::UpdateToMix(size_t maxAudioFrameCounter) const { 346 AudioFrameList AudioMixerImpl::UpdateToMix(size_t maxAudioFrameCounter) const {
371 AudioFrameList result; 347 AudioFrameList result;
372 std::vector<SourceFrame> audioSourceMixingDataList; 348 std::vector<SourceFrame> audioSourceMixingDataList;
373 349
374 // Get audio source audio and put it in the struct vector. 350 // Get audio source audio and put it in the struct vector.
375 for (MixerAudioSource* audio_source : audio_source_list_) { 351 for (MixerAudioSource* audio_source : audio_source_list_) {
376 auto audio_frame_with_info = audio_source->GetAudioFrameWithMuted( 352 auto audio_frame_with_info = audio_source->GetAudioFrameWithMuted(
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
584 return level; 560 return level;
585 } 561 }
586 562
587 int AudioMixerImpl::GetOutputAudioLevelFullRange() { 563 int AudioMixerImpl::GetOutputAudioLevelFullRange() {
588 const int level = audio_level_.LevelFullRange(); 564 const int level = audio_level_.LevelFullRange();
589 WEBRTC_TRACE(kTraceStateInfo, kTraceAudioMixerServer, id_, 565 WEBRTC_TRACE(kTraceStateInfo, kTraceAudioMixerServer, id_,
590 "GetAudioOutputLevelFullRange() => level=%d", level); 566 "GetAudioOutputLevelFullRange() => level=%d", level);
591 return level; 567 return level;
592 } 568 }
593 } // namespace webrtc 569 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698