| 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_options.h" | 5 #include "content/renderer/media/media_stream_audio_processor_options.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 std::string the_value; | 293 std::string the_value; |
| 294 if (GetConstraintValueAsString( | 294 if (GetConstraintValueAsString( |
| 295 constraints_, &blink::WebMediaTrackConstraintSet::googArrayGeometry, | 295 constraints_, &blink::WebMediaTrackConstraintSet::googArrayGeometry, |
| 296 &the_value)) { | 296 &the_value)) { |
| 297 return the_value; | 297 return the_value; |
| 298 } | 298 } |
| 299 return ""; | 299 return ""; |
| 300 } | 300 } |
| 301 | 301 |
| 302 EchoInformation::EchoInformation() | 302 EchoInformation::EchoInformation() |
| 303 : num_chunks_(0), echo_frames_received_(false) { | 303 : delay_stats_time_ms_(0), |
| 304 echo_frames_received_(false), |
| 305 divergent_filter_stats_time_ms_(0), |
| 306 num_divergent_filter_fraction_(0), |
| 307 num_non_zero_divergent_filter_fraction_(0) {} |
| 308 |
| 309 EchoInformation::~EchoInformation() { |
| 310 DCHECK(thread_checker_.CalledOnValidThread()); |
| 311 ReportAndResetAecDivergentFilterStats(); |
| 304 } | 312 } |
| 305 | 313 |
| 306 EchoInformation::~EchoInformation() {} | 314 void EchoInformation::UpdateAecStats( |
| 315 webrtc::EchoCancellation* echo_cancellation) { |
| 316 DCHECK(thread_checker_.CalledOnValidThread()); |
| 317 |
| 318 if (!echo_cancellation->is_enabled()) |
| 319 return; |
| 320 |
| 321 UpdateAecDelayStats(echo_cancellation); |
| 322 UpdateAecDivergentFilterStats(echo_cancellation); |
| 323 } |
| 307 | 324 |
| 308 void EchoInformation::UpdateAecDelayStats( | 325 void EchoInformation::UpdateAecDelayStats( |
| 309 webrtc::EchoCancellation* echo_cancellation) { | 326 webrtc::EchoCancellation* echo_cancellation) { |
| 327 DCHECK(thread_checker_.CalledOnValidThread()); |
| 328 |
| 310 // Only start collecting stats if we know echo cancellation has measured an | 329 // Only start collecting stats if we know echo cancellation has measured an |
| 311 // echo. Otherwise we clutter the stats with for example cases where only the | 330 // echo. Otherwise we clutter the stats with for example cases where only the |
| 312 // microphone is used. | 331 // microphone is used. |
| 313 if (!echo_frames_received_ & !echo_cancellation->stream_has_echo()) | 332 if (!echo_frames_received_ & !echo_cancellation->stream_has_echo()) |
| 314 return; | 333 return; |
| 315 | 334 |
| 316 echo_frames_received_ = true; | 335 echo_frames_received_ = true; |
| 336 |
| 317 // In WebRTC, three echo delay metrics are calculated and updated every | 337 // In WebRTC, three echo delay metrics are calculated and updated every |
| 318 // five seconds. We use one of them, |fraction_poor_delays| to log in a UMA | 338 // five seconds. We use one of them, |fraction_poor_delays| to log in a UMA |
| 319 // histogram an Echo Cancellation quality metric. The stat in WebRTC has a | 339 // histogram an Echo Cancellation quality metric. The stat in WebRTC has a |
| 320 // fixed aggregation window of five seconds, so we use the same query | 340 // fixed aggregation window of five seconds, so we use the same query |
| 321 // frequency to avoid logging old values. | 341 // frequency to avoid logging old values. |
| 322 const int kNumChunksInFiveSeconds = 500; | 342 if (!echo_cancellation->is_delay_logging_enabled()) |
| 323 if (!echo_cancellation->is_delay_logging_enabled() || | 343 return; |
| 324 !echo_cancellation->is_enabled()) { | 344 |
| 345 delay_stats_time_ms_ += webrtc::AudioProcessing::kChunkSizeMs; |
| 346 if (delay_stats_time_ms_ < |
| 347 500 * webrtc::AudioProcessing::kChunkSizeMs) { // 5 seconds |
| 325 return; | 348 return; |
| 326 } | 349 } |
| 327 | 350 |
| 328 num_chunks_++; | |
| 329 if (num_chunks_ < kNumChunksInFiveSeconds) { | |
| 330 return; | |
| 331 } | |
| 332 | |
| 333 int dummy_median = 0, dummy_std = 0; | 351 int dummy_median = 0, dummy_std = 0; |
| 334 float fraction_poor_delays = 0; | 352 float fraction_poor_delays = 0; |
| 335 if (echo_cancellation->GetDelayMetrics( | 353 if (echo_cancellation->GetDelayMetrics( |
| 336 &dummy_median, &dummy_std, &fraction_poor_delays) == | 354 &dummy_median, &dummy_std, &fraction_poor_delays) == |
| 337 webrtc::AudioProcessing::kNoError) { | 355 webrtc::AudioProcessing::kNoError) { |
| 338 num_chunks_ = 0; | 356 delay_stats_time_ms_ = 0; |
| 339 // Map |fraction_poor_delays| to an Echo Cancellation quality and log in UMA | 357 // Map |fraction_poor_delays| to an Echo Cancellation quality and log in UMA |
| 340 // histogram. See DelayBasedEchoQuality for information on histogram | 358 // histogram. See DelayBasedEchoQuality for information on histogram |
| 341 // buckets. | 359 // buckets. |
| 342 UMA_HISTOGRAM_ENUMERATION("WebRTC.AecDelayBasedQuality", | 360 UMA_HISTOGRAM_ENUMERATION("WebRTC.AecDelayBasedQuality", |
| 343 EchoDelayFrequencyToQuality(fraction_poor_delays), | 361 EchoDelayFrequencyToQuality(fraction_poor_delays), |
| 344 DELAY_BASED_ECHO_QUALITY_MAX); | 362 DELAY_BASED_ECHO_QUALITY_MAX); |
| 345 } | 363 } |
| 346 } | 364 } |
| 347 | 365 |
| 366 void EchoInformation::UpdateAecDivergentFilterStats( |
| 367 webrtc::EchoCancellation* echo_cancellation) { |
| 368 DCHECK(thread_checker_.CalledOnValidThread()); |
| 369 |
| 370 if (!echo_cancellation->are_metrics_enabled()) |
| 371 return; |
| 372 |
| 373 divergent_filter_stats_time_ms_ += webrtc::AudioProcessing::kChunkSizeMs; |
| 374 if (divergent_filter_stats_time_ms_ < |
| 375 100 * webrtc::AudioProcessing::kChunkSizeMs) { // 1 second |
| 376 return; |
| 377 } |
| 378 |
| 379 webrtc::EchoCancellation::Metrics metrics; |
| 380 if (echo_cancellation->GetMetrics(&metrics) == |
| 381 webrtc::AudioProcessing::kNoError) { |
| 382 // If not yet calculated, |metrics.divergent_filter_fraction| is -1.0. After |
| 383 // being calculated the first time, it is updated periodically. |
| 384 if (metrics.divergent_filter_fraction < 0.0f) { |
| 385 DCHECK_EQ(num_divergent_filter_fraction_, 0); |
| 386 return; |
| 387 } |
| 388 if (metrics.divergent_filter_fraction > 0.0f) { |
| 389 ++num_non_zero_divergent_filter_fraction_; |
| 390 } |
| 391 } else { |
| 392 DLOG(WARNING) << "Get echo cancellation metrics failed."; |
| 393 } |
| 394 ++num_divergent_filter_fraction_; |
| 395 divergent_filter_stats_time_ms_ = 0; |
| 396 } |
| 397 |
| 398 void EchoInformation::ReportAndResetAecDivergentFilterStats() { |
| 399 DCHECK(thread_checker_.CalledOnValidThread()); |
| 400 |
| 401 if (num_divergent_filter_fraction_ == 0) |
| 402 return; |
| 403 |
| 404 int non_zero_percent = 100 * num_non_zero_divergent_filter_fraction_ / |
| 405 num_divergent_filter_fraction_; |
| 406 UMA_HISTOGRAM_PERCENTAGE("WebRTC.AecFilterHasDivergence", non_zero_percent); |
| 407 |
| 408 divergent_filter_stats_time_ms_ = 0; |
| 409 num_non_zero_divergent_filter_fraction_ = 0; |
| 410 num_divergent_filter_fraction_ = 0; |
| 411 } |
| 412 |
| 348 void EnableEchoCancellation(AudioProcessing* audio_processing) { | 413 void EnableEchoCancellation(AudioProcessing* audio_processing) { |
| 349 #if defined(OS_ANDROID) | 414 #if defined(OS_ANDROID) |
| 350 // Mobile devices are using AECM. | 415 // Mobile devices are using AECM. |
| 351 CHECK_EQ(0, audio_processing->echo_control_mobile()->set_routing_mode( | 416 CHECK_EQ(0, audio_processing->echo_control_mobile()->set_routing_mode( |
| 352 webrtc::EchoControlMobile::kSpeakerphone)); | 417 webrtc::EchoControlMobile::kSpeakerphone)); |
| 353 CHECK_EQ(0, audio_processing->echo_control_mobile()->Enable(true)); | 418 CHECK_EQ(0, audio_processing->echo_control_mobile()->Enable(true)); |
| 354 return; | 419 return; |
| 355 #endif | 420 #endif |
| 356 int err = audio_processing->echo_cancellation()->set_suppression_level( | 421 int err = audio_processing->echo_cancellation()->set_suppression_level( |
| 357 webrtc::EchoCancellation::kHighSuppression); | 422 webrtc::EchoCancellation::kHighSuppression); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 466 | 531 |
| 467 // Give preference to the audio constraint over the device-supplied mic | 532 // Give preference to the audio constraint over the device-supplied mic |
| 468 // positions. This is mainly for testing purposes. | 533 // positions. This is mainly for testing purposes. |
| 469 return WebrtcPointsFromMediaPoints( | 534 return WebrtcPointsFromMediaPoints( |
| 470 constraints_geometry.empty() | 535 constraints_geometry.empty() |
| 471 ? input_params.mic_positions | 536 ? input_params.mic_positions |
| 472 : media::ParsePointsFromString(constraints_geometry)); | 537 : media::ParsePointsFromString(constraints_geometry)); |
| 473 } | 538 } |
| 474 | 539 |
| 475 } // namespace content | 540 } // namespace content |
| OLD | NEW |