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

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

Issue 2402283003: Cleanup of the mixer interface. (Closed)
Patch Set: Formulation & upper case. Created 4 years, 2 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 #include <utility>
16 16
17 #include "webrtc/base/logging.h" 17 #include "webrtc/base/logging.h"
18 #include "webrtc/modules/audio_mixer/audio_frame_manipulator.h" 18 #include "webrtc/modules/audio_mixer/audio_frame_manipulator.h"
19 #include "webrtc/modules/utility/include/audio_frame_operations.h" 19 #include "webrtc/modules/utility/include/audio_frame_operations.h"
20 #include "webrtc/system_wrappers/include/trace.h"
21 20
22 namespace webrtc { 21 namespace webrtc {
23 namespace { 22 namespace {
24 23
25 struct SourceFrame { 24 struct SourceFrame {
26 SourceFrame(AudioMixerImpl::SourceStatus* source_status, 25 SourceFrame(AudioMixerImpl::SourceStatus* source_status,
27 AudioFrame* audio_frame, 26 AudioFrame* audio_frame,
28 bool muted) 27 bool muted)
29 : source_status(source_status), audio_frame(audio_frame), muted(muted) { 28 : source_status(source_status), audio_frame(audio_frame), muted(muted) {
30 RTC_DCHECK(source_status); 29 RTC_DCHECK(source_status);
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 float target_gain = source_frame.source_status->is_mixed ? 1 : 0; 73 float target_gain = source_frame.source_status->is_mixed ? 1 : 0;
75 Ramp(source_frame.audio_frame, source_frame.source_status->gain, 74 Ramp(source_frame.audio_frame, source_frame.source_status->gain,
76 target_gain); 75 target_gain);
77 source_frame.source_status->gain = target_gain; 76 source_frame.source_status->gain = target_gain;
78 } 77 }
79 } 78 }
80 79
81 // Mix the AudioFrames stored in audioFrameList into mixed_audio. 80 // Mix the AudioFrames stored in audioFrameList into mixed_audio.
82 int32_t MixFromList(AudioFrame* mixed_audio, 81 int32_t MixFromList(AudioFrame* mixed_audio,
83 const AudioFrameList& audio_frame_list, 82 const AudioFrameList& audio_frame_list,
84 int32_t id,
85 bool use_limiter) { 83 bool use_limiter) {
86 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id, 84 if (audio_frame_list.empty()) {
87 "MixFromList(mixed_audio, audio_frame_list)");
88 if (audio_frame_list.empty())
89 return 0; 85 return 0;
86 }
90 87
91 if (audio_frame_list.size() == 1) { 88 if (audio_frame_list.size() == 1) {
92 mixed_audio->timestamp_ = audio_frame_list.front()->timestamp_; 89 mixed_audio->timestamp_ = audio_frame_list.front()->timestamp_;
93 mixed_audio->elapsed_time_ms_ = audio_frame_list.front()->elapsed_time_ms_; 90 mixed_audio->elapsed_time_ms_ = audio_frame_list.front()->elapsed_time_ms_;
94 } else { 91 } else {
95 // TODO(wu): Issue 3390. 92 // TODO(wu): Issue 3390.
96 // Audio frame timestamp is only supported in one channel case. 93 // Audio frame timestamp is only supported in one channel case.
97 mixed_audio->timestamp_ = 0; 94 mixed_audio->timestamp_ = 0;
98 mixed_audio->elapsed_time_ms_ = -1; 95 mixed_audio->elapsed_time_ms_ = -1;
99 } 96 }
(...skipping 21 matching lines...) Expand all
121 118
122 AudioMixerImpl::SourceStatusList::const_iterator FindSourceInList( 119 AudioMixerImpl::SourceStatusList::const_iterator FindSourceInList(
123 AudioMixerImpl::Source const* audio_source, 120 AudioMixerImpl::Source const* audio_source,
124 AudioMixerImpl::SourceStatusList const* audio_source_list) { 121 AudioMixerImpl::SourceStatusList const* audio_source_list) {
125 return std::find_if(audio_source_list->begin(), audio_source_list->end(), 122 return std::find_if(audio_source_list->begin(), audio_source_list->end(),
126 [audio_source](const AudioMixerImpl::SourceStatus& p) { 123 [audio_source](const AudioMixerImpl::SourceStatus& p) {
127 return p.audio_source == audio_source; 124 return p.audio_source == audio_source;
128 }); 125 });
129 } 126 }
130 127
128 // TODO(aleloi): remove non-const version when WEBRTC only supports modern STL.
131 AudioMixerImpl::SourceStatusList::iterator FindSourceInList( 129 AudioMixerImpl::SourceStatusList::iterator FindSourceInList(
132 AudioMixerImpl::Source const* audio_source, 130 AudioMixerImpl::Source const* audio_source,
133 AudioMixerImpl::SourceStatusList* audio_source_list) { 131 AudioMixerImpl::SourceStatusList* audio_source_list) {
134 return std::find_if(audio_source_list->begin(), audio_source_list->end(), 132 return std::find_if(audio_source_list->begin(), audio_source_list->end(),
135 [audio_source](const AudioMixerImpl::SourceStatus& p) { 133 [audio_source](const AudioMixerImpl::SourceStatus& p) {
136 return p.audio_source == audio_source; 134 return p.audio_source == audio_source;
137 }); 135 });
138 } 136 }
139 137
140 } // namespace 138 } // namespace
141 139
142 std::unique_ptr<AudioMixer> AudioMixer::Create(int id) { 140 std::unique_ptr<AudioMixer> AudioMixer::Create() {
143 return AudioMixerImpl::Create(id); 141 return AudioMixerImpl::Create();
144 } 142 }
145 143
146 AudioMixerImpl::AudioMixerImpl(int id, std::unique_ptr<AudioProcessing> limiter) 144 AudioMixerImpl::AudioMixerImpl(std::unique_ptr<AudioProcessing> limiter)
147 : id_(id), 145 : audio_source_list_(),
148 audio_source_list_(),
149 additional_audio_source_list_(),
150 num_mixed_audio_sources_(0), 146 num_mixed_audio_sources_(0),
151 use_limiter_(true), 147 use_limiter_(true),
152 time_stamp_(0), 148 time_stamp_(0),
153 limiter_(std::move(limiter)) { 149 limiter_(std::move(limiter)) {
154 SetOutputFrequency(kDefaultFrequency); 150 SetOutputFrequency(kDefaultFrequency);
155 thread_checker_.DetachFromThread(); 151 thread_checker_.DetachFromThread();
156 } 152 }
157 153
158 AudioMixerImpl::~AudioMixerImpl() {} 154 AudioMixerImpl::~AudioMixerImpl() {}
159 155
160 std::unique_ptr<AudioMixerImpl> AudioMixerImpl::Create(int id) { 156 std::unique_ptr<AudioMixerImpl> AudioMixerImpl::Create() {
161 Config config; 157 Config config;
162 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); 158 config.Set<ExperimentalAgc>(new ExperimentalAgc(false));
163 std::unique_ptr<AudioProcessing> limiter(AudioProcessing::Create(config)); 159 std::unique_ptr<AudioProcessing> limiter(AudioProcessing::Create(config));
164 if (!limiter.get()) 160 if (!limiter.get()) {
165 return nullptr; 161 return nullptr;
162 }
166 163
167 if (limiter->gain_control()->set_mode(GainControl::kFixedDigital) != 164 if (limiter->gain_control()->set_mode(GainControl::kFixedDigital) !=
168 limiter->kNoError) 165 limiter->kNoError) {
169 return nullptr; 166 return nullptr;
167 }
170 168
171 // We smoothly limit the mixed frame to -7 dbFS. -6 would correspond to the 169 // We smoothly limit the mixed frame to -7 dbFS. -6 would correspond to the
172 // divide-by-2 but -7 is used instead to give a bit of headroom since the 170 // divide-by-2 but -7 is used instead to give a bit of headroom since the
173 // AGC is not a hard limiter. 171 // AGC is not a hard limiter.
174 if (limiter->gain_control()->set_target_level_dbfs(7) != limiter->kNoError) 172 if (limiter->gain_control()->set_target_level_dbfs(7) != limiter->kNoError) {
175 return nullptr; 173 return nullptr;
174 }
176 175
177 if (limiter->gain_control()->set_compression_gain_db(0) != limiter->kNoError) 176 if (limiter->gain_control()->set_compression_gain_db(0) !=
177 limiter->kNoError) {
178 return nullptr; 178 return nullptr;
179 }
179 180
180 if (limiter->gain_control()->enable_limiter(true) != limiter->kNoError) 181 if (limiter->gain_control()->enable_limiter(true) != limiter->kNoError) {
181 return nullptr; 182 return nullptr;
183 }
182 184
183 if (limiter->gain_control()->Enable(true) != limiter->kNoError) 185 if (limiter->gain_control()->Enable(true) != limiter->kNoError) {
184 return nullptr; 186 return nullptr;
187 }
185 188
186 return std::unique_ptr<AudioMixerImpl>( 189 return std::unique_ptr<AudioMixerImpl>(
187 new AudioMixerImpl(id, std::move(limiter))); 190 new AudioMixerImpl(std::move(limiter)));
188 } 191 }
189 192
190 void AudioMixerImpl::Mix(int sample_rate, 193 void AudioMixerImpl::Mix(int sample_rate,
191 size_t number_of_channels, 194 size_t number_of_channels,
192 AudioFrame* audio_frame_for_mixing) { 195 AudioFrame* audio_frame_for_mixing) {
193 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); 196 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2);
194 RTC_DCHECK_RUN_ON(&thread_checker_); 197 RTC_DCHECK_RUN_ON(&thread_checker_);
195 198
196 if (sample_rate != kNbInHz && sample_rate != kWbInHz &&
197 sample_rate != kSwbInHz && sample_rate != kFbInHz) {
198 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_,
199 "Invalid frequency: %d", sample_rate);
200 RTC_NOTREACHED();
201 return;
202 }
203 199
204 if (OutputFrequency() != sample_rate) { 200 if (OutputFrequency() != sample_rate) {
205 SetOutputFrequency(static_cast<Frequency>(sample_rate)); 201 SetOutputFrequency(sample_rate);
206 } 202 }
207 203
208 AudioFrameList mix_list; 204 AudioFrameList mix_list;
209 AudioFrameList anonymous_mix_list;
210 size_t num_mixed_audio_sources; 205 size_t num_mixed_audio_sources;
211 { 206 {
212 rtc::CritScope lock(&crit_); 207 rtc::CritScope lock(&crit_);
213 mix_list = GetNonAnonymousAudio(); 208 mix_list = GetNonAnonymousAudio();
214 anonymous_mix_list = GetAnonymousAudio();
215 num_mixed_audio_sources = num_mixed_audio_sources_; 209 num_mixed_audio_sources = num_mixed_audio_sources_;
216 } 210 }
217 211
218 mix_list.insert(mix_list.begin(), anonymous_mix_list.begin(),
219 anonymous_mix_list.end());
220
221 for (const auto& frame : mix_list) { 212 for (const auto& frame : mix_list) {
222 RemixFrame(frame, number_of_channels); 213 RemixFrame(frame, number_of_channels);
223 } 214 }
224 215
225 audio_frame_for_mixing->UpdateFrame( 216 audio_frame_for_mixing->UpdateFrame(
226 -1, time_stamp_, NULL, 0, OutputFrequency(), AudioFrame::kNormalSpeech, 217 -1, time_stamp_, NULL, 0, OutputFrequency(), AudioFrame::kNormalSpeech,
227 AudioFrame::kVadPassive, number_of_channels); 218 AudioFrame::kVadPassive, number_of_channels);
228 219
229 time_stamp_ += static_cast<uint32_t>(sample_size_); 220 time_stamp_ += static_cast<uint32_t>(sample_size_);
230 221
231 use_limiter_ = num_mixed_audio_sources > 1; 222 use_limiter_ = num_mixed_audio_sources > 1;
232 223
233 // We only use the limiter if we're actually mixing multiple streams. 224 // We only use the limiter if we're actually mixing multiple streams.
234 MixFromList(audio_frame_for_mixing, mix_list, id_, use_limiter_); 225 MixFromList(audio_frame_for_mixing, mix_list, use_limiter_);
235 226
236 if (audio_frame_for_mixing->samples_per_channel_ == 0) { 227 if (audio_frame_for_mixing->samples_per_channel_ == 0) {
237 // Nothing was mixed, set the audio samples to silence. 228 // Nothing was mixed, set the audio samples to silence.
238 audio_frame_for_mixing->samples_per_channel_ = sample_size_; 229 audio_frame_for_mixing->samples_per_channel_ = sample_size_;
239 audio_frame_for_mixing->Mute(); 230 audio_frame_for_mixing->Mute();
240 } else { 231 } else {
241 // Only call the limiter if we have something to mix. 232 // Only call the limiter if we have something to mix.
242 LimitMixedAudio(audio_frame_for_mixing); 233 LimitMixedAudio(audio_frame_for_mixing);
243 } 234 }
244 235
245 // Pass the final result to the level indicator.
246 audio_level_.ComputeLevel(*audio_frame_for_mixing);
247
248 return; 236 return;
249 } 237 }
250 238
251 int32_t AudioMixerImpl::SetOutputFrequency(const Frequency& frequency) { 239 void AudioMixerImpl::SetOutputFrequency(int frequency) {
252 RTC_DCHECK_RUN_ON(&thread_checker_); 240 RTC_DCHECK_RUN_ON(&thread_checker_);
253 output_frequency_ = frequency; 241 output_frequency_ = frequency;
254 sample_size_ = (output_frequency_ * kFrameDurationInMs) / 1000; 242 sample_size_ = (output_frequency_ * kFrameDurationInMs) / 1000;
255
256 return 0;
257 } 243 }
258 244
259 AudioMixer::Frequency AudioMixerImpl::OutputFrequency() const { 245 int AudioMixerImpl::OutputFrequency() const {
260 RTC_DCHECK_RUN_ON(&thread_checker_); 246 RTC_DCHECK_RUN_ON(&thread_checker_);
261 return output_frequency_; 247 return output_frequency_;
262 } 248 }
263 249
264 int32_t AudioMixerImpl::SetMixabilityStatus(Source* audio_source, 250 int32_t AudioMixerImpl::SetMixabilityStatus(Source* audio_source,
265 bool mixable) { 251 bool mixable) {
266 if (!mixable) {
267 // Anonymous audio sources are in a separate list. Make sure that the
268 // audio source is in the _audioSourceList if it is being mixed.
269 SetAnonymousMixabilityStatus(audio_source, false);
270 }
271 { 252 {
272 rtc::CritScope lock(&crit_); 253 rtc::CritScope lock(&crit_);
273 const bool is_mixed = FindSourceInList(audio_source, &audio_source_list_) != 254 const bool is_mixed = FindSourceInList(audio_source, &audio_source_list_) !=
274 audio_source_list_.end(); 255 audio_source_list_.end();
275 // API must be called with a new state. 256 // API must be called with a new state.
276 if (!(mixable ^ is_mixed)) { 257 if (!(mixable ^ is_mixed)) {
277 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_,
278 "Mixable is aready %s", is_mixed ? "ON" : "off");
279 return -1; 258 return -1;
280 } 259 }
281 bool success = false; 260 bool success = false;
282 if (mixable) { 261 if (mixable) {
283 success = AddAudioSourceToList(audio_source, &audio_source_list_); 262 success = AddAudioSourceToList(audio_source, &audio_source_list_);
284 } else { 263 } else {
285 success = RemoveAudioSourceFromList(audio_source, &audio_source_list_); 264 success = RemoveAudioSourceFromList(audio_source, &audio_source_list_);
286 } 265 }
287 if (!success) { 266 if (!success) {
288 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_,
289 "failed to %s audio_source", mixable ? "add" : "remove");
290 RTC_NOTREACHED(); 267 RTC_NOTREACHED();
291 return -1; 268 return -1;
292 } 269 }
293 270
294 size_t num_mixed_non_anonymous = audio_source_list_.size(); 271 size_t num_mixed_non_anonymous = audio_source_list_.size();
295 if (num_mixed_non_anonymous > kMaximumAmountOfMixedAudioSources) { 272 if (num_mixed_non_anonymous > kMaximumAmountOfMixedAudioSources) {
296 num_mixed_non_anonymous = kMaximumAmountOfMixedAudioSources; 273 num_mixed_non_anonymous = kMaximumAmountOfMixedAudioSources;
297 } 274 }
298 num_mixed_audio_sources_ = 275 num_mixed_audio_sources_ = num_mixed_non_anonymous;
299 num_mixed_non_anonymous + additional_audio_source_list_.size();
300 } 276 }
301 return 0; 277 return 0;
302 } 278 }
303 279
304 bool AudioMixerImpl::MixabilityStatus(const Source& audio_source) const {
305 rtc::CritScope lock(&crit_);
306 return FindSourceInList(&audio_source, &audio_source_list_) !=
307 audio_source_list_.end();
308 }
309 280
310 int32_t AudioMixerImpl::SetAnonymousMixabilityStatus(Source* audio_source,
311 bool anonymous) {
312 rtc::CritScope lock(&crit_);
313 if (FindSourceInList(audio_source, &additional_audio_source_list_) !=
314 additional_audio_source_list_.end()) {
315 if (anonymous) {
316 return 0;
317 }
318 if (!RemoveAudioSourceFromList(audio_source,
319 &additional_audio_source_list_)) {
320 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_,
321 "unable to remove audio_source from anonymous list");
322 RTC_NOTREACHED();
323 return -1;
324 }
325 return AddAudioSourceToList(audio_source, &audio_source_list_) ? 0 : -1;
326 }
327 if (!anonymous) {
328 return 0;
329 }
330 const bool mixable =
331 RemoveAudioSourceFromList(audio_source, &audio_source_list_);
332 if (!mixable) {
333 WEBRTC_TRACE(
334 kTraceWarning, kTraceAudioMixerServer, id_,
335 "audio_source must be registered before turning it into anonymous");
336 // Setting anonymous status is only possible if MixerAudioSource is
337 // already registered.
338 return -1;
339 }
340 return AddAudioSourceToList(audio_source, &additional_audio_source_list_)
341 ? 0
342 : -1;
343 }
344
345 bool AudioMixerImpl::AnonymousMixabilityStatus(
346 const Source& audio_source) const {
347 rtc::CritScope lock(&crit_);
348 return FindSourceInList(&audio_source, &additional_audio_source_list_) !=
349 additional_audio_source_list_.end();
350 }
351 281
352 AudioFrameList AudioMixerImpl::GetNonAnonymousAudio() { 282 AudioFrameList AudioMixerImpl::GetNonAnonymousAudio() {
353 RTC_DCHECK_RUN_ON(&thread_checker_); 283 RTC_DCHECK_RUN_ON(&thread_checker_);
354 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
355 "GetNonAnonymousAudio()");
356 AudioFrameList result; 284 AudioFrameList result;
357 std::vector<SourceFrame> audio_source_mixing_data_list; 285 std::vector<SourceFrame> audio_source_mixing_data_list;
358 std::vector<SourceFrame> ramp_list; 286 std::vector<SourceFrame> ramp_list;
359 287
360 // Get audio source audio and put it in the struct vector. 288 // Get audio source audio and put it in the struct vector.
361 for (auto& source_and_status : audio_source_list_) { 289 for (auto& source_and_status : audio_source_list_) {
362 auto audio_frame_with_info = 290 auto audio_frame_with_info =
363 source_and_status.audio_source->GetAudioFrameWithMuted( 291 source_and_status.audio_source->GetAudioFrameWithMuted(
364 id_, static_cast<int>(OutputFrequency())); 292 static_cast<int>(OutputFrequency()));
365 293
366 const auto audio_frame_info = audio_frame_with_info.audio_frame_info; 294 const auto audio_frame_info = audio_frame_with_info.audio_frame_info;
367 AudioFrame* audio_source_audio_frame = audio_frame_with_info.audio_frame; 295 AudioFrame* audio_source_audio_frame = audio_frame_with_info.audio_frame;
368 296
369 if (audio_frame_info == Source::AudioFrameInfo::kError) { 297 if (audio_frame_info == Source::AudioFrameInfo::kError) {
370 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_, 298 LOG_F(LS_WARNING) << "Failed to GetAudioFrameWithMuted() from source";
371 "failed to GetAudioFrameWithMuted() from source");
372 continue; 299 continue;
373 } 300 }
374 audio_source_mixing_data_list.emplace_back( 301 audio_source_mixing_data_list.emplace_back(
375 &source_and_status, audio_source_audio_frame, 302 &source_and_status, audio_source_audio_frame,
376 audio_frame_info == Source::AudioFrameInfo::kMuted); 303 audio_frame_info == Source::AudioFrameInfo::kMuted);
377 } 304 }
378 305
379 // Sort frames by sorting function. 306 // Sort frames by sorting function.
380 std::sort(audio_source_mixing_data_list.begin(), 307 std::sort(audio_source_mixing_data_list.begin(),
381 audio_source_mixing_data_list.end(), ShouldMixBefore); 308 audio_source_mixing_data_list.end(), ShouldMixBefore);
(...skipping 15 matching lines...) Expand all
397 result.push_back(p.audio_frame); 324 result.push_back(p.audio_frame);
398 ramp_list.emplace_back(p.source_status, p.audio_frame, false, -1); 325 ramp_list.emplace_back(p.source_status, p.audio_frame, false, -1);
399 is_mixed = true; 326 is_mixed = true;
400 } 327 }
401 p.source_status->is_mixed = is_mixed; 328 p.source_status->is_mixed = is_mixed;
402 } 329 }
403 RampAndUpdateGain(ramp_list); 330 RampAndUpdateGain(ramp_list);
404 return result; 331 return result;
405 } 332 }
406 333
407 AudioFrameList AudioMixerImpl::GetAnonymousAudio() {
408 RTC_DCHECK_RUN_ON(&thread_checker_);
409 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
410 "GetAnonymousAudio()");
411 std::vector<SourceFrame> ramp_list;
412 AudioFrameList result;
413 for (auto& source_and_status : additional_audio_source_list_) {
414 const auto audio_frame_with_info =
415 source_and_status.audio_source->GetAudioFrameWithMuted(
416 id_, OutputFrequency());
417 const auto ret = audio_frame_with_info.audio_frame_info;
418 AudioFrame* audio_frame = audio_frame_with_info.audio_frame;
419 if (ret == Source::AudioFrameInfo::kError) {
420 WEBRTC_TRACE(kTraceWarning, kTraceAudioMixerServer, id_,
421 "failed to GetAudioFrameWithMuted() from audio_source");
422 continue;
423 }
424 if (ret != Source::AudioFrameInfo::kMuted) {
425 result.push_back(audio_frame);
426 ramp_list.emplace_back(&source_and_status, audio_frame, false, 0);
427 source_and_status.is_mixed = true;
428 }
429 }
430 RampAndUpdateGain(ramp_list);
431 return result;
432 }
433
434 bool AudioMixerImpl::AddAudioSourceToList( 334 bool AudioMixerImpl::AddAudioSourceToList(
435 Source* audio_source, 335 Source* audio_source,
436 SourceStatusList* audio_source_list) const { 336 SourceStatusList* audio_source_list) const {
437 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
438 "AddAudioSourceToList(audio_source, audio_source_list)");
439 audio_source_list->emplace_back(audio_source, false, 0); 337 audio_source_list->emplace_back(audio_source, false, 0);
440 return true; 338 return true;
441 } 339 }
442 340
443 bool AudioMixerImpl::RemoveAudioSourceFromList( 341 bool AudioMixerImpl::RemoveAudioSourceFromList(
444 Source* audio_source, 342 Source* audio_source,
445 SourceStatusList* audio_source_list) const { 343 SourceStatusList* audio_source_list) const {
446 WEBRTC_TRACE(kTraceStream, kTraceAudioMixerServer, id_,
447 "RemoveAudioSourceFromList(audio_source, audio_source_list)");
448 const auto iter = FindSourceInList(audio_source, audio_source_list); 344 const auto iter = FindSourceInList(audio_source, audio_source_list);
449 if (iter != audio_source_list->end()) { 345 if (iter != audio_source_list->end()) {
450 audio_source_list->erase(iter); 346 audio_source_list->erase(iter);
451 return true; 347 return true;
452 } else { 348 } else {
453 return false; 349 return false;
454 } 350 }
455 } 351 }
456 352
457 bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixed_audio) const { 353 bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixed_audio) const {
(...skipping 11 matching lines...) Expand all
469 // It's possible to apply the gain in the AGC (with a target level of 0 dbFS 365 // It's possible to apply the gain in the AGC (with a target level of 0 dbFS
470 // and compression gain of 6 dB). However, in the transition frame when this 366 // and compression gain of 6 dB). However, in the transition frame when this
471 // is enabled (moving from one to two audio sources) it has the potential to 367 // is enabled (moving from one to two audio sources) it has the potential to
472 // create discontinuities in the mixed frame. 368 // create discontinuities in the mixed frame.
473 // 369 //
474 // Instead we double the frame (with addition since left-shifting a 370 // Instead we double the frame (with addition since left-shifting a
475 // negative value is undefined). 371 // negative value is undefined).
476 *mixed_audio += *mixed_audio; 372 *mixed_audio += *mixed_audio;
477 373
478 if (error != limiter_->kNoError) { 374 if (error != limiter_->kNoError) {
479 WEBRTC_TRACE(kTraceError, kTraceAudioMixerServer, id_, 375 LOG_F(LS_ERROR) << "Error from AudioProcessing: " << error;
480 "Error from AudioProcessing: %d", error);
481 RTC_NOTREACHED(); 376 RTC_NOTREACHED();
482 return false; 377 return false;
483 } 378 }
484 return true; 379 return true;
485 } 380 }
486 381
487 int AudioMixerImpl::GetOutputAudioLevel() {
488 RTC_DCHECK_RUN_ON(&thread_checker_);
489 const int level = audio_level_.Level();
490 WEBRTC_TRACE(kTraceStateInfo, kTraceAudioMixerServer, id_,
491 "GetAudioOutputLevel() => level=%d", level);
492 return level;
493 }
494
495 int AudioMixerImpl::GetOutputAudioLevelFullRange() {
496 RTC_DCHECK_RUN_ON(&thread_checker_);
497 const int level = audio_level_.LevelFullRange();
498 WEBRTC_TRACE(kTraceStateInfo, kTraceAudioMixerServer, id_,
499 "GetAudioOutputLevelFullRange() => level=%d", level);
500 return level;
501 }
502
503 bool AudioMixerImpl::GetAudioSourceMixabilityStatusForTest( 382 bool AudioMixerImpl::GetAudioSourceMixabilityStatusForTest(
504 AudioMixerImpl::Source* audio_source) { 383 AudioMixerImpl::Source* audio_source) const {
505 RTC_DCHECK_RUN_ON(&thread_checker_); 384 RTC_DCHECK_RUN_ON(&thread_checker_);
506 rtc::CritScope lock(&crit_); 385 rtc::CritScope lock(&crit_);
507 386
508 const auto non_anonymous_iter = 387 const auto non_anonymous_iter =
509 FindSourceInList(audio_source, &audio_source_list_); 388 FindSourceInList(audio_source, &audio_source_list_);
510 if (non_anonymous_iter != audio_source_list_.end()) { 389 if (non_anonymous_iter != audio_source_list_.end()) {
511 return non_anonymous_iter->is_mixed; 390 return non_anonymous_iter->is_mixed;
512 } 391 }
513 392
514 const auto anonymous_iter =
515 FindSourceInList(audio_source, &additional_audio_source_list_);
516 if (anonymous_iter != audio_source_list_.end()) {
517 return anonymous_iter->is_mixed;
518 }
519
520 LOG(LS_ERROR) << "Audio source unknown"; 393 LOG(LS_ERROR) << "Audio source unknown";
521 return false; 394 return false;
522 } 395 }
523 } // namespace webrtc 396 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698