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

Side by Side Diff: content/renderer/media/media_stream_audio_processor.cc

Issue 227743004: Added a kEchoCancellation constraint to turn off the audio processing. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: addressed the comments. Created 6 years, 8 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 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/media/media_stream_audio_processor.h" 5 #include "content/renderer/media/media_stream_audio_processor.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/debug/trace_event.h" 8 #include "base/debug/trace_event.h"
9 #include "base/metrics/field_trial.h" 9 #include "base/metrics/field_trial.h"
10 #include "base/metrics/histogram.h" 10 #include "base/metrics/histogram.h"
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 // TODO(xians): consider using SincResampler to save some memcpy. 150 // TODO(xians): consider using SincResampler to save some memcpy.
151 // Handles mixing and resampling between input and output parameters. 151 // Handles mixing and resampling between input and output parameters.
152 media::AudioConverter audio_converter_; 152 media::AudioConverter audio_converter_;
153 scoped_ptr<media::AudioBus> audio_wrapper_; 153 scoped_ptr<media::AudioBus> audio_wrapper_;
154 scoped_ptr<media::AudioFifo> fifo_; 154 scoped_ptr<media::AudioFifo> fifo_;
155 }; 155 };
156 156
157 MediaStreamAudioProcessor::MediaStreamAudioProcessor( 157 MediaStreamAudioProcessor::MediaStreamAudioProcessor(
158 const blink::WebMediaConstraints& constraints, 158 const blink::WebMediaConstraints& constraints,
159 int effects, 159 int effects,
160 MediaStreamType type,
161 WebRtcPlayoutDataSource* playout_data_source) 160 WebRtcPlayoutDataSource* playout_data_source)
162 : render_delay_ms_(0), 161 : render_delay_ms_(0),
163 playout_data_source_(playout_data_source), 162 playout_data_source_(playout_data_source),
164 audio_mirroring_(false), 163 goog_audio_mirroring_(false),
perkj_chrome 2014/04/11 11:45:04 why prefix with goog?
no longer working on chromium 2014/04/11 16:47:05 They are from goog* constraints, and Tommi suggest
165 typing_detected_(false) { 164 goog_typing_detected_(false) {
166 capture_thread_checker_.DetachFromThread(); 165 capture_thread_checker_.DetachFromThread();
167 render_thread_checker_.DetachFromThread(); 166 render_thread_checker_.DetachFromThread();
168 InitializeAudioProcessingModule(constraints, effects, type); 167 InitializeAudioProcessingModule(constraints, effects);
169 } 168 }
170 169
171 MediaStreamAudioProcessor::~MediaStreamAudioProcessor() { 170 MediaStreamAudioProcessor::~MediaStreamAudioProcessor() {
172 DCHECK(main_thread_checker_.CalledOnValidThread()); 171 DCHECK(main_thread_checker_.CalledOnValidThread());
173 StopAudioProcessing(); 172 StopAudioProcessing();
174 } 173 }
175 174
176 void MediaStreamAudioProcessor::OnCaptureFormatChanged( 175 void MediaStreamAudioProcessor::OnCaptureFormatChanged(
177 const media::AudioParameters& source_params) { 176 const media::AudioParameters& source_params) {
178 DCHECK(main_thread_checker_.CalledOnValidThread()); 177 DCHECK(main_thread_checker_.CalledOnValidThread());
179 // There is no need to hold a lock here since the caller guarantees that 178 // There is no need to hold a lock here since the caller guarantees that
180 // there is no more PushCaptureData() and ProcessAndConsumeData() callbacks 179 // there is no more PushCaptureData() and ProcessAndConsumeData() callbacks
181 // on the capture thread. 180 // on the capture thread.
182 InitializeCaptureConverter(source_params); 181 InitializeCaptureConverter(source_params);
183 182
184 // Reset the |capture_thread_checker_| since the capture data will come from 183 // Reset the |capture_thread_checker_| since the capture data will come from
185 // a new capture thread. 184 // a new capture thread.
186 capture_thread_checker_.DetachFromThread(); 185 capture_thread_checker_.DetachFromThread();
187 } 186 }
188 187
189 void MediaStreamAudioProcessor::PushCaptureData(media::AudioBus* audio_source) { 188 void MediaStreamAudioProcessor::PushCaptureData(media::AudioBus* audio_source) {
190 DCHECK(capture_thread_checker_.CalledOnValidThread()); 189 DCHECK(capture_thread_checker_.CalledOnValidThread());
191 DCHECK_EQ(audio_source->channels(), 190 DCHECK_EQ(audio_source->channels(),
192 capture_converter_->source_parameters().channels()); 191 capture_converter_->source_parameters().channels());
193 DCHECK_EQ(audio_source->frames(), 192 DCHECK_EQ(audio_source->frames(),
194 capture_converter_->source_parameters().frames_per_buffer()); 193 capture_converter_->source_parameters().frames_per_buffer());
195 194
196 if (audio_mirroring_ && 195 if (goog_audio_mirroring_ &&
197 capture_converter_->source_parameters().channel_layout() == 196 capture_converter_->source_parameters().channel_layout() ==
198 media::CHANNEL_LAYOUT_STEREO) { 197 media::CHANNEL_LAYOUT_STEREO) {
199 // Swap the first and second channels. 198 // Swap the first and second channels.
200 audio_source->SwapChannels(0, 1); 199 audio_source->SwapChannels(0, 1);
201 } 200 }
202 201
203 capture_converter_->Push(audio_source); 202 capture_converter_->Push(audio_source);
204 } 203 }
205 204
206 bool MediaStreamAudioProcessor::ProcessAndConsumeData( 205 bool MediaStreamAudioProcessor::ProcessAndConsumeData(
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 void MediaStreamAudioProcessor::OnPlayoutDataSourceChanged() { 263 void MediaStreamAudioProcessor::OnPlayoutDataSourceChanged() {
265 DCHECK(main_thread_checker_.CalledOnValidThread()); 264 DCHECK(main_thread_checker_.CalledOnValidThread());
266 // There is no need to hold a lock here since the caller guarantees that 265 // There is no need to hold a lock here since the caller guarantees that
267 // there is no more OnPlayoutData() callback on the render thread. 266 // there is no more OnPlayoutData() callback on the render thread.
268 render_thread_checker_.DetachFromThread(); 267 render_thread_checker_.DetachFromThread();
269 render_converter_.reset(); 268 render_converter_.reset();
270 } 269 }
271 270
272 void MediaStreamAudioProcessor::GetStats(AudioProcessorStats* stats) { 271 void MediaStreamAudioProcessor::GetStats(AudioProcessorStats* stats) {
273 stats->typing_noise_detected = 272 stats->typing_noise_detected =
274 (base::subtle::Acquire_Load(&typing_detected_) != false); 273 (base::subtle::Acquire_Load(&goog_typing_detected_) != false);
275 GetAecStats(audio_processing_.get(), stats); 274 GetAecStats(audio_processing_.get(), stats);
276 } 275 }
277 276
278 void MediaStreamAudioProcessor::InitializeAudioProcessingModule( 277 void MediaStreamAudioProcessor::InitializeAudioProcessingModule(
279 const blink::WebMediaConstraints& constraints, int effects, 278 const blink::WebMediaConstraints& constraints, int effects) {
280 MediaStreamType type) {
281 DCHECK(!audio_processing_); 279 DCHECK(!audio_processing_);
282 280
283 RTCMediaConstraints native_constraints(constraints);
284
285 // Audio mirroring can be enabled even though audio processing is otherwise 281 // Audio mirroring can be enabled even though audio processing is otherwise
286 // disabled. 282 // disabled.
287 audio_mirroring_ = GetPropertyFromConstraints( 283 goog_audio_mirroring_ = GetPropertyFromConstraints(
288 &native_constraints, webrtc::MediaConstraintsInterface::kAudioMirroring); 284 constraints, kGoogAudioMirroring, effects);
289 285
290 if (!IsAudioTrackProcessingEnabled()) { 286 if (!IsAudioTrackProcessingEnabled()) {
291 RecordProcessingState(AUDIO_PROCESSING_IN_WEBRTC); 287 RecordProcessingState(AUDIO_PROCESSING_IN_WEBRTC);
292 return; 288 return;
293 } 289 }
294 290
295 // Only apply the fixed constraints for gUM of MEDIA_DEVICE_AUDIO_CAPTURE. 291 // |kEchoCancellation| is used as a master control on enabling/disabling
296 DCHECK(IsAudioMediaType(type)); 292 // the audio processing.
297 if (type == MEDIA_DEVICE_AUDIO_CAPTURE) 293 const bool echo_cancellation = GetPropertyFromConstraints(
298 ApplyFixedAudioConstraints(&native_constraints); 294 constraints, kEchoCancellation, effects);
299 295 if (!echo_cancellation) {
300 if (effects & media::AudioParameters::ECHO_CANCELLER) { 296 RecordProcessingState(AUDIO_PROCESSING_DISABLED);
301 // If platform echo canceller is enabled, disable the software AEC. 297 return;
302 native_constraints.AddMandatory(
303 MediaConstraintsInterface::kEchoCancellation,
304 MediaConstraintsInterface::kValueFalse, true);
305 } 298 }
306 299
307 #if defined(OS_IOS) 300 #if defined(OS_IOS)
308 // On iOS, VPIO provides built-in AEC and AGC. 301 // On iOS, VPIO provides built-in AEC and AGC.
309 const bool enable_aec = false; 302 const bool goog_aec = false;
310 const bool enable_agc = false; 303 const bool goog_agc = false;
311 #else 304 #else
312 const bool enable_aec = GetPropertyFromConstraints( 305 // TODO(xians): goog_aec should be just echo_cancellation.
perkj_chrome 2014/04/11 11:45:04 ???
no longer working on chromium 2014/04/11 16:47:05 I am thinking that kEchoCancellation can replace k
perkj_chrome 2014/04/14 12:15:19 no. Maybe refrase to goog_aec should be renamed to
313 &native_constraints, MediaConstraintsInterface::kEchoCancellation); 306 const bool goog_aec = GetPropertyFromConstraints(
314 const bool enable_agc = GetPropertyFromConstraints( 307 constraints, kGoogEchoCancellation, effects);
315 &native_constraints, webrtc::MediaConstraintsInterface::kAutoGainControl); 308 const bool goog_agc = GetPropertyFromConstraints(
309 constraints, kGoogAutoGainControl, effects);
316 #endif 310 #endif
317 311
318 #if defined(OS_IOS) || defined(OS_ANDROID) 312 #if defined(OS_IOS) || defined(OS_ANDROID)
319 const bool enable_experimental_aec = false; 313 const bool goog_experimental_aec = false;
320 const bool enable_typing_detection = false; 314 const bool goog_typing_detection = false;
321 #else 315 #else
322 const bool enable_experimental_aec = GetPropertyFromConstraints( 316 const bool goog_experimental_aec = GetPropertyFromConstraints(
323 &native_constraints, 317 constraints, kGoogExperimentalEchoCancellation, effects);
324 MediaConstraintsInterface::kExperimentalEchoCancellation); 318 const bool goog_typing_detection = GetPropertyFromConstraints(
325 const bool enable_typing_detection = GetPropertyFromConstraints( 319 constraints, kGoogTypingNoiseDetection, effects);
326 &native_constraints, MediaConstraintsInterface::kTypingNoiseDetection);
327 #endif 320 #endif
328 321
329 const bool enable_ns = GetPropertyFromConstraints( 322 const bool goog_ns = GetPropertyFromConstraints(
330 &native_constraints, MediaConstraintsInterface::kNoiseSuppression); 323 constraints, kGoogNoiseSuppression, effects);
331 const bool enable_experimental_ns = GetPropertyFromConstraints( 324 const bool goog_experimental_ns = GetPropertyFromConstraints(
332 &native_constraints, 325 constraints, kGoogExperimentalNoiseSuppression, effects);
333 MediaConstraintsInterface::kExperimentalNoiseSuppression); 326 const bool goog_high_pass_filter = GetPropertyFromConstraints(
334 const bool enable_high_pass_filter = GetPropertyFromConstraints( 327 constraints, kGoogHighpassFilter, effects);
335 &native_constraints, MediaConstraintsInterface::kHighpassFilter);
336 328
337 // Return immediately if no audio processing component is enabled. 329 // Return immediately if no goog constraint is enabled.
338 if (!enable_aec && !enable_experimental_aec && !enable_ns && 330 if (!goog_aec && !goog_experimental_aec && !goog_ns &&
339 !enable_high_pass_filter && !enable_typing_detection && !enable_agc && 331 !goog_high_pass_filter && !goog_typing_detection &&
340 !enable_experimental_ns) { 332 !goog_agc && !goog_experimental_ns) {
341 RecordProcessingState(AUDIO_PROCESSING_DISABLED); 333 RecordProcessingState(AUDIO_PROCESSING_DISABLED);
342 return; 334 return;
343 } 335 }
344 336
345 // Create and configure the webrtc::AudioProcessing. 337 // Create and configure the webrtc::AudioProcessing.
346 audio_processing_.reset(webrtc::AudioProcessing::Create(0)); 338 audio_processing_.reset(webrtc::AudioProcessing::Create(0));
347 339
348 // Enable the audio processing components. 340 // Enable the audio processing components.
349 if (enable_aec) { 341 if (goog_aec) {
350 EnableEchoCancellation(audio_processing_.get()); 342 EnableEchoCancellation(audio_processing_.get());
351 if (enable_experimental_aec) 343 if (goog_experimental_aec)
352 EnableExperimentalEchoCancellation(audio_processing_.get()); 344 EnableExperimentalEchoCancellation(audio_processing_.get());
353 345
354 if (playout_data_source_) 346 if (playout_data_source_)
355 playout_data_source_->AddPlayoutSink(this); 347 playout_data_source_->AddPlayoutSink(this);
356 } 348 }
357 349
358 if (enable_ns) 350 if (goog_ns)
359 EnableNoiseSuppression(audio_processing_.get()); 351 EnableNoiseSuppression(audio_processing_.get());
360 352
361 if (enable_experimental_ns) 353 if (goog_experimental_ns)
362 EnableExperimentalNoiseSuppression(audio_processing_.get()); 354 EnableExperimentalNoiseSuppression(audio_processing_.get());
363 355
364 if (enable_high_pass_filter) 356 if (goog_high_pass_filter)
365 EnableHighPassFilter(audio_processing_.get()); 357 EnableHighPassFilter(audio_processing_.get());
366 358
367 if (enable_typing_detection) { 359 if (goog_typing_detection) {
368 // TODO(xians): Remove this |typing_detector_| after the typing suppression 360 // TODO(xians): Remove this |typing_detector_| after the typing suppression
369 // is enabled by default. 361 // is enabled by default.
370 typing_detector_.reset(new webrtc::TypingDetection()); 362 typing_detector_.reset(new webrtc::TypingDetection());
371 EnableTypingDetection(audio_processing_.get(), typing_detector_.get()); 363 EnableTypingDetection(audio_processing_.get(), typing_detector_.get());
372 } 364 }
373 365
374 if (enable_agc) 366 if (goog_agc)
375 EnableAutomaticGainControl(audio_processing_.get()); 367 EnableAutomaticGainControl(audio_processing_.get());
376 368
377 // Configure the audio format the audio processing is running on. This 369 // Configure the audio format the audio processing is running on. This
378 // has to be done after all the needed components are enabled. 370 // has to be done after all the needed components are enabled.
379 CHECK_EQ(0, 371 CHECK_EQ(0,
380 audio_processing_->set_sample_rate_hz(kAudioProcessingSampleRate)); 372 audio_processing_->set_sample_rate_hz(kAudioProcessingSampleRate));
381 CHECK_EQ(0, audio_processing_->set_num_channels( 373 CHECK_EQ(0, audio_processing_->set_num_channels(
382 kAudioProcessingNumberOfChannels, kAudioProcessingNumberOfChannels)); 374 kAudioProcessingNumberOfChannels, kAudioProcessingNumberOfChannels));
383 375
384 RecordProcessingState(AUDIO_PROCESSING_ENABLED); 376 RecordProcessingState(AUDIO_PROCESSING_ENABLED);
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
481 audio_processing_->set_stream_key_pressed(key_pressed); 473 audio_processing_->set_stream_key_pressed(key_pressed);
482 474
483 err = audio_processing_->ProcessStream(audio_frame); 475 err = audio_processing_->ProcessStream(audio_frame);
484 DCHECK_EQ(err, 0) << "ProcessStream() error: " << err; 476 DCHECK_EQ(err, 0) << "ProcessStream() error: " << err;
485 477
486 if (typing_detector_ && 478 if (typing_detector_ &&
487 audio_frame->vad_activity_ != webrtc::AudioFrame::kVadUnknown) { 479 audio_frame->vad_activity_ != webrtc::AudioFrame::kVadUnknown) {
488 bool vad_active = 480 bool vad_active =
489 (audio_frame->vad_activity_ == webrtc::AudioFrame::kVadActive); 481 (audio_frame->vad_activity_ == webrtc::AudioFrame::kVadActive);
490 bool typing_detected = typing_detector_->Process(key_pressed, vad_active); 482 bool typing_detected = typing_detector_->Process(key_pressed, vad_active);
491 base::subtle::Release_Store(&typing_detected_, typing_detected); 483 base::subtle::Release_Store(&goog_typing_detected_, typing_detected);
492 } 484 }
493 485
494 // Return 0 if the volume has not been changed, otherwise return the new 486 // Return 0 if the volume has not been changed, otherwise return the new
495 // volume. 487 // volume.
496 return (agc->stream_analog_level() == volume) ? 488 return (agc->stream_analog_level() == volume) ?
497 0 : agc->stream_analog_level(); 489 0 : agc->stream_analog_level();
498 } 490 }
499 491
500 void MediaStreamAudioProcessor::StopAudioProcessing() { 492 void MediaStreamAudioProcessor::StopAudioProcessing() {
501 if (!audio_processing_.get()) 493 if (!audio_processing_.get())
502 return; 494 return;
503 495
504 StopAecDump(); 496 StopAecDump();
505 497
506 if (playout_data_source_) 498 if (playout_data_source_)
507 playout_data_source_->RemovePlayoutSink(this); 499 playout_data_source_->RemovePlayoutSink(this);
508 500
509 audio_processing_.reset(); 501 audio_processing_.reset();
510 } 502 }
511 503
512 bool MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled() const { 504 bool MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled() const {
513 const std::string group_name = 505 const std::string group_name =
514 base::FieldTrialList::FindFullName("MediaStreamAudioTrackProcessing"); 506 base::FieldTrialList::FindFullName("MediaStreamAudioTrackProcessing");
515 return group_name == "Enabled" || CommandLine::ForCurrentProcess()->HasSwitch( 507 return group_name == "Enabled" || CommandLine::ForCurrentProcess()->HasSwitch(
516 switches::kEnableAudioTrackProcessing); 508 switches::kEnableAudioTrackProcessing);
517 } 509 }
518 510
519 } // namespace content 511 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698