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

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

Issue 2408683002: Cleanup of the mixer interface. (Closed)
Patch Set: Rebase 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
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 AudioMixerImpl::Source const* audio_source, 130 AudioMixerImpl::Source const* audio_source,
131 AudioMixerImpl::SourceStatusList* audio_source_list) { 131 AudioMixerImpl::SourceStatusList* audio_source_list) {
132 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(),
133 [audio_source](const AudioMixerImpl::SourceStatus& p) { 133 [audio_source](const AudioMixerImpl::SourceStatus& p) {
134 return p.audio_source == audio_source; 134 return p.audio_source == audio_source;
135 }); 135 });
136 } 136 }
137 137
138 } // namespace 138 } // namespace
139 139
140 std::unique_ptr<AudioMixer> AudioMixer::Create() {
141 return AudioMixerImpl::Create();
142 }
143
144 AudioMixerImpl::AudioMixerImpl(std::unique_ptr<AudioProcessing> limiter) 140 AudioMixerImpl::AudioMixerImpl(std::unique_ptr<AudioProcessing> limiter)
145 : audio_source_list_(), 141 : audio_source_list_(),
146 num_mixed_audio_sources_(0),
147 use_limiter_(true), 142 use_limiter_(true),
148 time_stamp_(0), 143 time_stamp_(0),
149 limiter_(std::move(limiter)) { 144 limiter_(std::move(limiter)) {
150 SetOutputFrequency(kDefaultFrequency); 145 SetOutputFrequency(kDefaultFrequency);
151 thread_checker_.DetachFromThread(); 146 thread_checker_.DetachFromThread();
152 } 147 }
153 148
154 AudioMixerImpl::~AudioMixerImpl() {} 149 AudioMixerImpl::~AudioMixerImpl() {}
155 150
156 std::unique_ptr<AudioMixerImpl> AudioMixerImpl::Create() { 151 rtc::scoped_refptr<AudioMixerImpl> AudioMixerImpl::Create() {
157 Config config; 152 Config config;
158 config.Set<ExperimentalAgc>(new ExperimentalAgc(false)); 153 config.Set<ExperimentalAgc>(new ExperimentalAgc(false));
159 std::unique_ptr<AudioProcessing> limiter(AudioProcessing::Create(config)); 154 std::unique_ptr<AudioProcessing> limiter(AudioProcessing::Create(config));
160 if (!limiter.get()) { 155 if (!limiter.get()) {
161 return nullptr; 156 return nullptr;
162 } 157 }
163 158
164 if (limiter->gain_control()->set_mode(GainControl::kFixedDigital) != 159 if (limiter->gain_control()->set_mode(GainControl::kFixedDigital) !=
165 limiter->kNoError) { 160 limiter->kNoError) {
166 return nullptr; 161 return nullptr;
(...skipping 12 matching lines...) Expand all
179 } 174 }
180 175
181 if (limiter->gain_control()->enable_limiter(true) != limiter->kNoError) { 176 if (limiter->gain_control()->enable_limiter(true) != limiter->kNoError) {
182 return nullptr; 177 return nullptr;
183 } 178 }
184 179
185 if (limiter->gain_control()->Enable(true) != limiter->kNoError) { 180 if (limiter->gain_control()->Enable(true) != limiter->kNoError) {
186 return nullptr; 181 return nullptr;
187 } 182 }
188 183
189 return std::unique_ptr<AudioMixerImpl>( 184 return rtc::scoped_refptr<AudioMixerImpl>(
190 new AudioMixerImpl(std::move(limiter))); 185 new rtc::RefCountedObject<AudioMixerImpl>(std::move(limiter)));
191 } 186 }
192 187
193 void AudioMixerImpl::Mix(int sample_rate, 188 void AudioMixerImpl::Mix(int sample_rate,
194 size_t number_of_channels, 189 size_t number_of_channels,
195 AudioFrame* audio_frame_for_mixing) { 190 AudioFrame* audio_frame_for_mixing) {
196 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2); 191 RTC_DCHECK(number_of_channels == 1 || number_of_channels == 2);
197 RTC_DCHECK_RUN_ON(&thread_checker_); 192 RTC_DCHECK_RUN_ON(&thread_checker_);
198 193
199 194
200 if (OutputFrequency() != sample_rate) { 195 if (OutputFrequency() != sample_rate) {
201 SetOutputFrequency(sample_rate); 196 SetOutputFrequency(sample_rate);
202 } 197 }
203 198
204 AudioFrameList mix_list; 199 AudioFrameList mix_list;
205 size_t num_mixed_audio_sources;
206 { 200 {
207 rtc::CritScope lock(&crit_); 201 rtc::CritScope lock(&crit_);
208 mix_list = GetNonAnonymousAudio(); 202 mix_list = GetAudioFromSources();
209 num_mixed_audio_sources = num_mixed_audio_sources_;
210 } 203 }
211 204
212 for (const auto& frame : mix_list) { 205 for (const auto& frame : mix_list) {
213 RemixFrame(frame, number_of_channels); 206 RemixFrame(frame, number_of_channels);
214 } 207 }
215 208
216 audio_frame_for_mixing->UpdateFrame( 209 audio_frame_for_mixing->UpdateFrame(
217 -1, time_stamp_, NULL, 0, OutputFrequency(), AudioFrame::kNormalSpeech, 210 -1, time_stamp_, NULL, 0, OutputFrequency(), AudioFrame::kNormalSpeech,
218 AudioFrame::kVadPassive, number_of_channels); 211 AudioFrame::kVadPassive, number_of_channels);
219 212
220 time_stamp_ += static_cast<uint32_t>(sample_size_); 213 time_stamp_ += static_cast<uint32_t>(sample_size_);
221 214
222 use_limiter_ = num_mixed_audio_sources > 1; 215 use_limiter_ = mix_list.size() > 1;
223 216
224 // We only use the limiter if we're actually mixing multiple streams. 217 // We only use the limiter if we're actually mixing multiple streams.
225 MixFromList(audio_frame_for_mixing, mix_list, use_limiter_); 218 MixFromList(audio_frame_for_mixing, mix_list, use_limiter_);
226 219
227 if (audio_frame_for_mixing->samples_per_channel_ == 0) { 220 if (audio_frame_for_mixing->samples_per_channel_ == 0) {
228 // Nothing was mixed, set the audio samples to silence. 221 // Nothing was mixed, set the audio samples to silence.
229 audio_frame_for_mixing->samples_per_channel_ = sample_size_; 222 audio_frame_for_mixing->samples_per_channel_ = sample_size_;
230 audio_frame_for_mixing->Mute(); 223 audio_frame_for_mixing->Mute();
231 } else { 224 } else {
232 // Only call the limiter if we have something to mix. 225 // Only call the limiter if we have something to mix.
233 LimitMixedAudio(audio_frame_for_mixing); 226 LimitMixedAudio(audio_frame_for_mixing);
234 } 227 }
235 228
236 return; 229 return;
237 } 230 }
238 231
239 void AudioMixerImpl::SetOutputFrequency(int frequency) { 232 void AudioMixerImpl::SetOutputFrequency(int frequency) {
240 RTC_DCHECK_RUN_ON(&thread_checker_); 233 RTC_DCHECK_RUN_ON(&thread_checker_);
241 output_frequency_ = frequency; 234 output_frequency_ = frequency;
242 sample_size_ = (output_frequency_ * kFrameDurationInMs) / 1000; 235 sample_size_ = (output_frequency_ * kFrameDurationInMs) / 1000;
243 } 236 }
244 237
245 int AudioMixerImpl::OutputFrequency() const { 238 int AudioMixerImpl::OutputFrequency() const {
246 RTC_DCHECK_RUN_ON(&thread_checker_); 239 RTC_DCHECK_RUN_ON(&thread_checker_);
247 return output_frequency_; 240 return output_frequency_;
248 } 241 }
249 242
250 int32_t AudioMixerImpl::SetMixabilityStatus(Source* audio_source, 243 bool AudioMixerImpl::AddSource(Source* audio_source) {
251 bool mixable) { 244 RTC_DCHECK(audio_source);
252 { 245 rtc::CritScope lock(&crit_);
253 rtc::CritScope lock(&crit_); 246 RTC_DCHECK(FindSourceInList(audio_source, &audio_source_list_) ==
hlundin-webrtc 2016/10/11 11:50:21 The argument of DCHECK is not evaluated in release
the sun 2016/10/11 12:10:56 That's exactly the point. Don't evaluate since it
254 const bool is_mixed = FindSourceInList(audio_source, &audio_source_list_) != 247 audio_source_list_.end())
255 audio_source_list_.end(); 248 << "Source already added to mixer";
256 // API must be called with a new state. 249 audio_source_list_.emplace_back(audio_source, false, 0);
257 if (!(mixable ^ is_mixed)) { 250 return true;
258 return -1;
259 }
260 bool success = false;
261 if (mixable) {
262 success = AddAudioSourceToList(audio_source, &audio_source_list_);
263 } else {
264 success = RemoveAudioSourceFromList(audio_source, &audio_source_list_);
265 }
266 if (!success) {
267 RTC_NOTREACHED();
268 return -1;
269 }
270
271 size_t num_mixed_non_anonymous = audio_source_list_.size();
272 if (num_mixed_non_anonymous > kMaximumAmountOfMixedAudioSources) {
273 num_mixed_non_anonymous = kMaximumAmountOfMixedAudioSources;
274 }
275 num_mixed_audio_sources_ = num_mixed_non_anonymous;
276 }
277 return 0;
278 } 251 }
279 252
253 bool AudioMixerImpl::RemoveSource(Source* audio_source) {
254 RTC_DCHECK(audio_source);
255 rtc::CritScope lock(&crit_);
256 const auto iter = FindSourceInList(audio_source, &audio_source_list_);
257 RTC_DCHECK(iter != audio_source_list_.end()) << "Source not present in mixer";
hlundin-webrtc 2016/10/11 11:50:21 Same here.
the sun 2016/10/11 12:10:56 But here "iter" is used for the deletion.
hlundin-webrtc 2016/10/11 12:49:54 Yes, iter is needed in any case. I was referring t
258 audio_source_list_.erase(iter);
259 return true;
260 }
280 261
281 262 AudioFrameList AudioMixerImpl::GetAudioFromSources() {
282 AudioFrameList AudioMixerImpl::GetNonAnonymousAudio() {
283 RTC_DCHECK_RUN_ON(&thread_checker_); 263 RTC_DCHECK_RUN_ON(&thread_checker_);
284 AudioFrameList result; 264 AudioFrameList result;
285 std::vector<SourceFrame> audio_source_mixing_data_list; 265 std::vector<SourceFrame> audio_source_mixing_data_list;
286 std::vector<SourceFrame> ramp_list; 266 std::vector<SourceFrame> ramp_list;
287 267
288 // Get audio source audio and put it in the struct vector. 268 // Get audio source audio and put it in the struct vector.
289 for (auto& source_and_status : audio_source_list_) { 269 for (auto& source_and_status : audio_source_list_) {
290 auto audio_frame_with_info = 270 auto audio_frame_with_info =
291 source_and_status.audio_source->GetAudioFrameWithMuted( 271 source_and_status.audio_source->GetAudioFrameWithMuted(
292 static_cast<int>(OutputFrequency())); 272 static_cast<int>(OutputFrequency()));
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 result.push_back(p.audio_frame); 304 result.push_back(p.audio_frame);
325 ramp_list.emplace_back(p.source_status, p.audio_frame, false, -1); 305 ramp_list.emplace_back(p.source_status, p.audio_frame, false, -1);
326 is_mixed = true; 306 is_mixed = true;
327 } 307 }
328 p.source_status->is_mixed = is_mixed; 308 p.source_status->is_mixed = is_mixed;
329 } 309 }
330 RampAndUpdateGain(ramp_list); 310 RampAndUpdateGain(ramp_list);
331 return result; 311 return result;
332 } 312 }
333 313
334 bool AudioMixerImpl::AddAudioSourceToList(
335 Source* audio_source,
336 SourceStatusList* audio_source_list) const {
337 audio_source_list->emplace_back(audio_source, false, 0);
338 return true;
339 }
340
341 bool AudioMixerImpl::RemoveAudioSourceFromList(
342 Source* audio_source,
343 SourceStatusList* audio_source_list) const {
344 const auto iter = FindSourceInList(audio_source, audio_source_list);
345 if (iter != audio_source_list->end()) {
346 audio_source_list->erase(iter);
347 return true;
348 } else {
349 return false;
350 }
351 }
352 314
353 bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixed_audio) const { 315 bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixed_audio) const {
354 RTC_DCHECK_RUN_ON(&thread_checker_); 316 RTC_DCHECK_RUN_ON(&thread_checker_);
355 if (!use_limiter_) { 317 if (!use_limiter_) {
356 return true; 318 return true;
357 } 319 }
358 320
359 // Smoothly limit the mixed frame. 321 // Smoothly limit the mixed frame.
360 const int error = limiter_->ProcessStream(mixed_audio); 322 const int error = limiter_->ProcessStream(mixed_audio);
361 323
(...skipping 25 matching lines...) Expand all
387 const auto non_anonymous_iter = 349 const auto non_anonymous_iter =
388 FindSourceInList(audio_source, &audio_source_list_); 350 FindSourceInList(audio_source, &audio_source_list_);
389 if (non_anonymous_iter != audio_source_list_.end()) { 351 if (non_anonymous_iter != audio_source_list_.end()) {
390 return non_anonymous_iter->is_mixed; 352 return non_anonymous_iter->is_mixed;
391 } 353 }
392 354
393 LOG(LS_ERROR) << "Audio source unknown"; 355 LOG(LS_ERROR) << "Audio source unknown";
394 return false; 356 return false;
395 } 357 }
396 } // namespace webrtc 358 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698