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

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

Issue 2408683002: Cleanup of the mixer interface. (Closed)
Patch Set: 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;
aleloi 2016/10/10 13:06:31 This change slightly alters the mixing behavior. I
the sun 2016/10/10 13:35:49 Acknowledged.
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) {
the sun 2016/10/10 13:35:49 RTC_DCHECK(audio_source);
251 bool mixable) { 244 rtc::CritScope lock(&crit_);
252 { 245 const bool is_mixed = FindSourceInList(audio_source, &audio_source_list_) !=
253 rtc::CritScope lock(&crit_); 246 audio_source_list_.end();
254 const bool is_mixed = FindSourceInList(audio_source, &audio_source_list_) != 247 if (is_mixed) {
255 audio_source_list_.end(); 248 LOG(LS_WARNING) << "Source already added to mixer";
256 // API must be called with a new state. 249 return false;
the sun 2016/10/10 13:35:49 I think you should just DCHECK(!is_mixed) and alwa
aleloi 2016/10/10 14:02:27 I agree: it's better to see this as an error inste
257 if (!(mixable ^ is_mixed)) {
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 } 250 }
277 return 0; 251 audio_source_list_.emplace_back(audio_source, false, 0);
252 return true;
278 } 253 }
279 254
255 bool AudioMixerImpl::RemoveSource(Source* audio_source) {
the sun 2016/10/10 13:35:49 Same comments apply as in AddSource()
aleloi 2016/10/10 14:02:27 Done.
256 rtc::CritScope lock(&crit_);
257 const bool is_mixed = FindSourceInList(audio_source, &audio_source_list_) !=
258 audio_source_list_.end();
259 if (!is_mixed) {
260 return false;
261 }
262 const auto iter = FindSourceInList(audio_source, &audio_source_list_);
263 if (iter == audio_source_list_.end()) {
264 LOG_T_F(LS_WARNING) << "Source not present in mixer";
265 return false;
266 }
267 audio_source_list_.erase(iter);
268 return true;
269 }
280 270
281 271 AudioFrameList AudioMixerImpl::GetAudioFromSources() {
282 AudioFrameList AudioMixerImpl::GetNonAnonymousAudio() {
283 RTC_DCHECK_RUN_ON(&thread_checker_); 272 RTC_DCHECK_RUN_ON(&thread_checker_);
284 AudioFrameList result; 273 AudioFrameList result;
285 std::vector<SourceFrame> audio_source_mixing_data_list; 274 std::vector<SourceFrame> audio_source_mixing_data_list;
286 std::vector<SourceFrame> ramp_list; 275 std::vector<SourceFrame> ramp_list;
287 276
288 // Get audio source audio and put it in the struct vector. 277 // Get audio source audio and put it in the struct vector.
289 for (auto& source_and_status : audio_source_list_) { 278 for (auto& source_and_status : audio_source_list_) {
290 auto audio_frame_with_info = 279 auto audio_frame_with_info =
291 source_and_status.audio_source->GetAudioFrameWithMuted( 280 source_and_status.audio_source->GetAudioFrameWithMuted(
292 static_cast<int>(OutputFrequency())); 281 static_cast<int>(OutputFrequency()));
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 result.push_back(p.audio_frame); 313 result.push_back(p.audio_frame);
325 ramp_list.emplace_back(p.source_status, p.audio_frame, false, -1); 314 ramp_list.emplace_back(p.source_status, p.audio_frame, false, -1);
326 is_mixed = true; 315 is_mixed = true;
327 } 316 }
328 p.source_status->is_mixed = is_mixed; 317 p.source_status->is_mixed = is_mixed;
329 } 318 }
330 RampAndUpdateGain(ramp_list); 319 RampAndUpdateGain(ramp_list);
331 return result; 320 return result;
332 } 321 }
333 322
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 323
353 bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixed_audio) const { 324 bool AudioMixerImpl::LimitMixedAudio(AudioFrame* mixed_audio) const {
354 RTC_DCHECK_RUN_ON(&thread_checker_); 325 RTC_DCHECK_RUN_ON(&thread_checker_);
355 if (!use_limiter_) { 326 if (!use_limiter_) {
356 return true; 327 return true;
357 } 328 }
358 329
359 // Smoothly limit the mixed frame. 330 // Smoothly limit the mixed frame.
360 const int error = limiter_->ProcessStream(mixed_audio); 331 const int error = limiter_->ProcessStream(mixed_audio);
361 332
(...skipping 25 matching lines...) Expand all
387 const auto non_anonymous_iter = 358 const auto non_anonymous_iter =
388 FindSourceInList(audio_source, &audio_source_list_); 359 FindSourceInList(audio_source, &audio_source_list_);
389 if (non_anonymous_iter != audio_source_list_.end()) { 360 if (non_anonymous_iter != audio_source_list_.end()) {
390 return non_anonymous_iter->is_mixed; 361 return non_anonymous_iter->is_mixed;
391 } 362 }
392 363
393 LOG(LS_ERROR) << "Audio source unknown"; 364 LOG(LS_ERROR) << "Audio source unknown";
394 return false; 365 return false;
395 } 366 }
396 } // namespace webrtc 367 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698