Chromium Code Reviews| OLD | NEW |
|---|---|
| 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" |
| 11 #include "content/public/common/content_switches.h" | 11 #include "content/public/common/content_switches.h" |
| 12 #include "content/renderer/media/media_stream_audio_processor_options.h" | 12 #include "content/renderer/media/media_stream_audio_processor_options.h" |
| 13 #include "content/renderer/media/rtc_media_constraints.h" | 13 #include "content/renderer/media/rtc_media_constraints.h" |
| 14 #include "content/renderer/media/webrtc_audio_device_impl.h" | 14 #include "content/renderer/media/webrtc_audio_device_impl.h" |
| 15 #include "media/audio/audio_parameters.h" | 15 #include "media/audio/audio_parameters.h" |
| 16 #include "media/base/audio_converter.h" | 16 #include "media/base/audio_converter.h" |
| 17 #include "media/base/audio_fifo.h" | 17 #include "media/base/audio_fifo.h" |
| 18 #include "media/base/channel_layout.h" | 18 #include "media/base/channel_layout.h" |
| 19 #include "third_party/WebKit/public/platform/WebMediaConstraints.h" | 19 #include "third_party/WebKit/public/platform/WebMediaConstraints.h" |
| 20 #include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface .h" | 20 #include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface .h" |
| 21 #include "third_party/webrtc/modules/audio_processing/typing_detection.h" | 21 #include "third_party/webrtc/modules/audio_processing/typing_detection.h" |
| 22 | 22 |
| 23 namespace content { | 23 namespace content { |
| 24 | 24 |
| 25 namespace { | 25 namespace { |
| 26 | 26 |
| 27 using webrtc::AudioProcessing; | 27 using webrtc::AudioProcessing; |
| 28 using webrtc::MediaConstraintsInterface; | |
| 29 | 28 |
| 30 #if defined(OS_ANDROID) | 29 #if defined(OS_ANDROID) |
| 31 const int kAudioProcessingSampleRate = 16000; | 30 const int kAudioProcessingSampleRate = 16000; |
| 32 #else | 31 #else |
| 33 const int kAudioProcessingSampleRate = 32000; | 32 const int kAudioProcessingSampleRate = 32000; |
| 34 #endif | 33 #endif |
| 35 const int kAudioProcessingNumberOfChannels = 1; | 34 const int kAudioProcessingNumberOfChannels = 1; |
| 36 const AudioProcessing::ChannelLayout kAudioProcessingChannelLayout = | 35 const AudioProcessing::ChannelLayout kAudioProcessingChannelLayout = |
| 37 AudioProcessing::kMono; | 36 AudioProcessing::kMono; |
| 38 | 37 |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 160 bool MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled() { | 159 bool MediaStreamAudioProcessor::IsAudioTrackProcessingEnabled() { |
| 161 const std::string group_name = | 160 const std::string group_name = |
| 162 base::FieldTrialList::FindFullName("MediaStreamAudioTrackProcessing"); | 161 base::FieldTrialList::FindFullName("MediaStreamAudioTrackProcessing"); |
| 163 return group_name == "Enabled" || CommandLine::ForCurrentProcess()->HasSwitch( | 162 return group_name == "Enabled" || CommandLine::ForCurrentProcess()->HasSwitch( |
| 164 switches::kEnableAudioTrackProcessing); | 163 switches::kEnableAudioTrackProcessing); |
| 165 } | 164 } |
| 166 | 165 |
| 167 MediaStreamAudioProcessor::MediaStreamAudioProcessor( | 166 MediaStreamAudioProcessor::MediaStreamAudioProcessor( |
| 168 const blink::WebMediaConstraints& constraints, | 167 const blink::WebMediaConstraints& constraints, |
| 169 int effects, | 168 int effects, |
| 170 MediaStreamType type, | |
| 171 WebRtcPlayoutDataSource* playout_data_source) | 169 WebRtcPlayoutDataSource* playout_data_source) |
| 172 : render_delay_ms_(0), | 170 : render_delay_ms_(0), |
| 173 playout_data_source_(playout_data_source), | 171 playout_data_source_(playout_data_source), |
| 174 audio_mirroring_(false), | 172 audio_mirroring_(false), |
| 175 typing_detected_(false) { | 173 typing_detected_(false) { |
| 176 capture_thread_checker_.DetachFromThread(); | 174 capture_thread_checker_.DetachFromThread(); |
| 177 render_thread_checker_.DetachFromThread(); | 175 render_thread_checker_.DetachFromThread(); |
| 178 InitializeAudioProcessingModule(constraints, effects, type); | 176 InitializeAudioProcessingModule(constraints, effects); |
| 179 } | 177 } |
| 180 | 178 |
| 181 MediaStreamAudioProcessor::~MediaStreamAudioProcessor() { | 179 MediaStreamAudioProcessor::~MediaStreamAudioProcessor() { |
| 182 DCHECK(main_thread_checker_.CalledOnValidThread()); | 180 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 183 StopAudioProcessing(); | 181 StopAudioProcessing(); |
| 184 } | 182 } |
| 185 | 183 |
| 186 void MediaStreamAudioProcessor::OnCaptureFormatChanged( | 184 void MediaStreamAudioProcessor::OnCaptureFormatChanged( |
| 187 const media::AudioParameters& source_params) { | 185 const media::AudioParameters& source_params) { |
| 188 DCHECK(main_thread_checker_.CalledOnValidThread()); | 186 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 276 render_converter_.reset(); | 274 render_converter_.reset(); |
| 277 } | 275 } |
| 278 | 276 |
| 279 void MediaStreamAudioProcessor::GetStats(AudioProcessorStats* stats) { | 277 void MediaStreamAudioProcessor::GetStats(AudioProcessorStats* stats) { |
| 280 stats->typing_noise_detected = | 278 stats->typing_noise_detected = |
| 281 (base::subtle::Acquire_Load(&typing_detected_) != false); | 279 (base::subtle::Acquire_Load(&typing_detected_) != false); |
| 282 GetAecStats(audio_processing_.get(), stats); | 280 GetAecStats(audio_processing_.get(), stats); |
| 283 } | 281 } |
| 284 | 282 |
| 285 void MediaStreamAudioProcessor::InitializeAudioProcessingModule( | 283 void MediaStreamAudioProcessor::InitializeAudioProcessingModule( |
| 286 const blink::WebMediaConstraints& constraints, int effects, | 284 const blink::WebMediaConstraints& constraints, int effects) { |
| 287 MediaStreamType type) { | |
| 288 DCHECK(!audio_processing_); | 285 DCHECK(!audio_processing_); |
| 289 | 286 |
| 290 RTCMediaConstraints native_constraints(constraints); | 287 MediaAudioConstraints audio_constraints(constraints, effects); |
| 291 | 288 |
| 292 // Audio mirroring can be enabled even though audio processing is otherwise | 289 // Audio mirroring can be enabled even though audio processing is otherwise |
| 293 // disabled. | 290 // disabled. |
| 294 audio_mirroring_ = GetPropertyFromConstraints( | 291 audio_mirroring_ = audio_constraints.GetProperty( |
| 295 &native_constraints, webrtc::MediaConstraintsInterface::kAudioMirroring); | 292 MediaAudioConstraints::kGoogAudioMirroring); |
| 296 | 293 |
| 297 if (!IsAudioTrackProcessingEnabled()) { | 294 if (!IsAudioTrackProcessingEnabled()) { |
| 298 RecordProcessingState(AUDIO_PROCESSING_IN_WEBRTC); | 295 RecordProcessingState(AUDIO_PROCESSING_IN_WEBRTC); |
| 299 return; | 296 return; |
| 300 } | 297 } |
| 301 | 298 |
| 302 // Only apply the fixed constraints for gUM of MEDIA_DEVICE_AUDIO_CAPTURE. | |
| 303 DCHECK(IsAudioMediaType(type)); | |
| 304 if (type == MEDIA_DEVICE_AUDIO_CAPTURE) | |
| 305 ApplyFixedAudioConstraints(&native_constraints); | |
| 306 | |
| 307 if (effects & media::AudioParameters::ECHO_CANCELLER) { | |
| 308 // If platform echo canceller is enabled, disable the software AEC. | |
| 309 native_constraints.AddMandatory( | |
| 310 MediaConstraintsInterface::kEchoCancellation, | |
| 311 MediaConstraintsInterface::kValueFalse, true); | |
| 312 } | |
| 313 | |
| 314 #if defined(OS_IOS) | 299 #if defined(OS_IOS) |
| 315 // On iOS, VPIO provides built-in AEC and AGC. | 300 // On iOS, VPIO provides built-in AGC and AEC. |
| 316 const bool enable_aec = false; | 301 const bool echo_cancellation = false; |
| 317 const bool enable_agc = false; | 302 const bool goog_agc = false; |
| 318 #else | 303 #else |
| 319 const bool enable_aec = GetPropertyFromConstraints( | 304 const bool echo_cancellation = |
| 320 &native_constraints, MediaConstraintsInterface::kEchoCancellation); | 305 audio_constraints.GetEchoCancellationProperty(); |
|
tommi (sloooow) - chröme
2014/05/07 14:19:45
ah, this is nice. It makes this function so much e
| |
| 321 const bool enable_agc = GetPropertyFromConstraints( | 306 const bool goog_agc = audio_constraints.GetProperty( |
| 322 &native_constraints, webrtc::MediaConstraintsInterface::kAutoGainControl); | 307 MediaAudioConstraints::kGoogAutoGainControl); |
| 323 #endif | 308 #endif |
| 324 | 309 |
| 325 #if defined(OS_IOS) || defined(OS_ANDROID) | 310 #if defined(OS_IOS) || defined(OS_ANDROID) |
| 326 const bool enable_experimental_aec = false; | 311 const bool goog_experimental_aec = false; |
| 327 const bool enable_typing_detection = false; | 312 const bool goog_typing_detection = false; |
| 328 #else | 313 #else |
| 329 const bool enable_experimental_aec = GetPropertyFromConstraints( | 314 const bool goog_experimental_aec = audio_constraints.GetProperty( |
| 330 &native_constraints, | 315 MediaAudioConstraints::kGoogExperimentalEchoCancellation); |
| 331 MediaConstraintsInterface::kExperimentalEchoCancellation); | 316 const bool goog_typing_detection = audio_constraints.GetProperty( |
| 332 const bool enable_typing_detection = GetPropertyFromConstraints( | 317 MediaAudioConstraints::kGoogTypingNoiseDetection); |
| 333 &native_constraints, MediaConstraintsInterface::kTypingNoiseDetection); | |
| 334 #endif | 318 #endif |
| 335 | 319 |
| 336 const bool enable_ns = GetPropertyFromConstraints( | 320 const bool goog_ns = audio_constraints.GetProperty( |
| 337 &native_constraints, MediaConstraintsInterface::kNoiseSuppression); | 321 MediaAudioConstraints::kGoogNoiseSuppression); |
| 338 const bool enable_experimental_ns = GetPropertyFromConstraints( | 322 const bool goog_experimental_ns = audio_constraints.GetProperty( |
| 339 &native_constraints, | 323 MediaAudioConstraints::kGoogExperimentalNoiseSuppression); |
| 340 MediaConstraintsInterface::kExperimentalNoiseSuppression); | 324 const bool goog_high_pass_filter = audio_constraints.GetProperty( |
| 341 const bool enable_high_pass_filter = GetPropertyFromConstraints( | 325 MediaAudioConstraints::kGoogHighpassFilter); |
| 342 &native_constraints, MediaConstraintsInterface::kHighpassFilter); | |
| 343 | 326 |
| 344 // Return immediately if no audio processing component is enabled. | 327 // Return immediately if no goog constraint is enabled. |
| 345 if (!enable_aec && !enable_experimental_aec && !enable_ns && | 328 if (!echo_cancellation && !goog_experimental_aec && !goog_ns && |
| 346 !enable_high_pass_filter && !enable_typing_detection && !enable_agc && | 329 !goog_high_pass_filter && !goog_typing_detection && |
| 347 !enable_experimental_ns) { | 330 !goog_agc && !goog_experimental_ns) { |
| 348 RecordProcessingState(AUDIO_PROCESSING_DISABLED); | 331 RecordProcessingState(AUDIO_PROCESSING_DISABLED); |
| 349 return; | 332 return; |
| 350 } | 333 } |
| 351 | 334 |
| 352 // Create and configure the webrtc::AudioProcessing. | 335 // Create and configure the webrtc::AudioProcessing. |
| 353 audio_processing_.reset(webrtc::AudioProcessing::Create()); | 336 audio_processing_.reset(webrtc::AudioProcessing::Create()); |
| 354 CHECK_EQ(0, audio_processing_->Initialize(kAudioProcessingSampleRate, | 337 CHECK_EQ(0, audio_processing_->Initialize(kAudioProcessingSampleRate, |
| 355 kAudioProcessingSampleRate, | 338 kAudioProcessingSampleRate, |
| 356 kAudioProcessingSampleRate, | 339 kAudioProcessingSampleRate, |
| 357 kAudioProcessingChannelLayout, | 340 kAudioProcessingChannelLayout, |
| 358 kAudioProcessingChannelLayout, | 341 kAudioProcessingChannelLayout, |
| 359 kAudioProcessingChannelLayout)); | 342 kAudioProcessingChannelLayout)); |
| 360 | 343 |
| 361 // Enable the audio processing components. | 344 // Enable the audio processing components. |
| 362 if (enable_aec) { | 345 if (echo_cancellation) { |
| 363 EnableEchoCancellation(audio_processing_.get()); | 346 EnableEchoCancellation(audio_processing_.get()); |
| 364 if (enable_experimental_aec) | 347 |
| 348 if (goog_experimental_aec) | |
| 365 EnableExperimentalEchoCancellation(audio_processing_.get()); | 349 EnableExperimentalEchoCancellation(audio_processing_.get()); |
| 366 | 350 |
| 367 if (playout_data_source_) | 351 if (playout_data_source_) |
| 368 playout_data_source_->AddPlayoutSink(this); | 352 playout_data_source_->AddPlayoutSink(this); |
| 369 } | 353 } |
| 370 | 354 |
| 371 if (enable_ns) | 355 if (goog_ns) |
| 372 EnableNoiseSuppression(audio_processing_.get()); | 356 EnableNoiseSuppression(audio_processing_.get()); |
| 373 | 357 |
| 374 if (enable_experimental_ns) | 358 if (goog_experimental_ns) |
| 375 EnableExperimentalNoiseSuppression(audio_processing_.get()); | 359 EnableExperimentalNoiseSuppression(audio_processing_.get()); |
| 376 | 360 |
| 377 if (enable_high_pass_filter) | 361 if (goog_high_pass_filter) |
| 378 EnableHighPassFilter(audio_processing_.get()); | 362 EnableHighPassFilter(audio_processing_.get()); |
| 379 | 363 |
| 380 if (enable_typing_detection) { | 364 if (goog_typing_detection) { |
| 381 // TODO(xians): Remove this |typing_detector_| after the typing suppression | 365 // TODO(xians): Remove this |typing_detector_| after the typing suppression |
| 382 // is enabled by default. | 366 // is enabled by default. |
| 383 typing_detector_.reset(new webrtc::TypingDetection()); | 367 typing_detector_.reset(new webrtc::TypingDetection()); |
| 384 EnableTypingDetection(audio_processing_.get(), typing_detector_.get()); | 368 EnableTypingDetection(audio_processing_.get(), typing_detector_.get()); |
| 385 } | 369 } |
| 386 | 370 |
| 387 if (enable_agc) | 371 if (goog_agc) |
| 388 EnableAutomaticGainControl(audio_processing_.get()); | 372 EnableAutomaticGainControl(audio_processing_.get()); |
| 389 | 373 |
| 390 RecordProcessingState(AUDIO_PROCESSING_ENABLED); | 374 RecordProcessingState(AUDIO_PROCESSING_ENABLED); |
| 391 } | 375 } |
| 392 | 376 |
| 393 void MediaStreamAudioProcessor::InitializeCaptureConverter( | 377 void MediaStreamAudioProcessor::InitializeCaptureConverter( |
| 394 const media::AudioParameters& source_params) { | 378 const media::AudioParameters& source_params) { |
| 395 DCHECK(main_thread_checker_.CalledOnValidThread()); | 379 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 396 DCHECK(source_params.IsValid()); | 380 DCHECK(source_params.IsValid()); |
| 397 | 381 |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 510 | 494 |
| 511 StopAecDump(); | 495 StopAecDump(); |
| 512 | 496 |
| 513 if (playout_data_source_) | 497 if (playout_data_source_) |
| 514 playout_data_source_->RemovePlayoutSink(this); | 498 playout_data_source_->RemovePlayoutSink(this); |
| 515 | 499 |
| 516 audio_processing_.reset(); | 500 audio_processing_.reset(); |
| 517 } | 501 } |
| 518 | 502 |
| 519 } // namespace content | 503 } // namespace content |
| OLD | NEW |