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_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 : chunks_for_delay_stats_(0), |
| 304 echo_frames_received_(false), | |
| 305 chunks_for_divergent_filter_stats_(0), | |
| 306 num_divergent_filter_fraction_(0), | |
| 307 num_non_zero_divergent_filter_fraction_(0) {} | |
| 308 | |
| 309 EchoInformation::~EchoInformation() { | |
| 310 ReportAndResetAecDivergentFilterStats(); | |
| 304 } | 311 } |
| 305 | 312 |
| 306 EchoInformation::~EchoInformation() {} | |
| 307 | |
| 308 void EchoInformation::UpdateAecDelayStats( | 313 void EchoInformation::UpdateAecDelayStats( |
| 309 webrtc::EchoCancellation* echo_cancellation) { | 314 webrtc::EchoCancellation* echo_cancellation) { |
| 310 // Only start collecting stats if we know echo cancellation has measured an | 315 // 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 | 316 // echo. Otherwise we clutter the stats with for example cases where only the |
| 312 // microphone is used. | 317 // microphone is used. |
| 313 if (!echo_frames_received_ & !echo_cancellation->stream_has_echo()) | 318 if (!echo_frames_received_ & !echo_cancellation->stream_has_echo()) |
| 314 return; | 319 return; |
| 315 | 320 |
| 316 echo_frames_received_ = true; | 321 echo_frames_received_ = true; |
| 317 // In WebRTC, three echo delay metrics are calculated and updated every | 322 // 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 | 323 // 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 | 324 // 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 | 325 // fixed aggregation window of five seconds, so we use the same query |
| 321 // frequency to avoid logging old values. | 326 // frequency to avoid logging old values. |
| 322 const int kNumChunksInFiveSeconds = 500; | 327 const int kNumChunksInFiveSeconds = 500; |
| 323 if (!echo_cancellation->is_delay_logging_enabled() || | 328 if (!echo_cancellation->is_delay_logging_enabled() || |
| 324 !echo_cancellation->is_enabled()) { | 329 !echo_cancellation->is_enabled()) { |
| 325 return; | 330 return; |
| 326 } | 331 } |
| 327 | 332 |
| 328 num_chunks_++; | 333 ++chunks_for_delay_stats_; |
| 329 if (num_chunks_ < kNumChunksInFiveSeconds) { | 334 if (chunks_for_delay_stats_ < kNumChunksInFiveSeconds) |
| 330 return; | 335 return; |
| 331 } | |
| 332 | 336 |
| 333 int dummy_median = 0, dummy_std = 0; | 337 int dummy_median = 0, dummy_std = 0; |
| 334 float fraction_poor_delays = 0; | 338 float fraction_poor_delays = 0; |
| 335 if (echo_cancellation->GetDelayMetrics( | 339 if (echo_cancellation->GetDelayMetrics( |
| 336 &dummy_median, &dummy_std, &fraction_poor_delays) == | 340 &dummy_median, &dummy_std, &fraction_poor_delays) == |
| 337 webrtc::AudioProcessing::kNoError) { | 341 webrtc::AudioProcessing::kNoError) { |
| 338 num_chunks_ = 0; | 342 chunks_for_delay_stats_ = 0; |
| 339 // Map |fraction_poor_delays| to an Echo Cancellation quality and log in UMA | 343 // Map |fraction_poor_delays| to an Echo Cancellation quality and log in UMA |
| 340 // histogram. See DelayBasedEchoQuality for information on histogram | 344 // histogram. See DelayBasedEchoQuality for information on histogram |
| 341 // buckets. | 345 // buckets. |
| 342 UMA_HISTOGRAM_ENUMERATION("WebRTC.AecDelayBasedQuality", | 346 UMA_HISTOGRAM_ENUMERATION("WebRTC.AecDelayBasedQuality", |
| 343 EchoDelayFrequencyToQuality(fraction_poor_delays), | 347 EchoDelayFrequencyToQuality(fraction_poor_delays), |
| 344 DELAY_BASED_ECHO_QUALITY_MAX); | 348 DELAY_BASED_ECHO_QUALITY_MAX); |
| 345 } | 349 } |
| 346 } | 350 } |
| 347 | 351 |
| 352 void EchoInformation::UpdateAecDivergentFilterStats( | |
| 353 webrtc::EchoCancellation* echo_cancellation) { | |
| 354 if (!echo_cancellation->is_enabled() || | |
| 355 !echo_cancellation->are_metrics_enabled()) { | |
| 356 return; | |
| 357 } | |
| 358 | |
| 359 const int kNumChunksInOneSecond = 100; | |
|
minyue
2016/06/28 08:18:41
kNumChunksInOneSecond and kNumChunksInFiveSeconds
Henrik Grunell
2016/06/28 09:33:10
Using time and kChunkDurationMs.
| |
| 360 ++chunks_for_divergent_filter_stats_; | |
| 361 if (chunks_for_divergent_filter_stats_ < kNumChunksInOneSecond) | |
| 362 return; | |
| 363 | |
| 364 webrtc::EchoCancellation::Metrics metrics; | |
| 365 if (echo_cancellation->GetMetrics(&metrics) == | |
| 366 webrtc::AudioProcessing::kNoError) { | |
| 367 // If not yet calculated, |metrics.divergent_filter_fraction| is -1.0. After | |
| 368 // being calculated the first time, it is updated periodically. | |
| 369 if (metrics.divergent_filter_fraction < 0.0f) { | |
| 370 DCHECK_EQ(num_divergent_filter_fraction_, 0); | |
| 371 return; | |
| 372 } | |
| 373 if (metrics.divergent_filter_fraction > 0.0f) { | |
| 374 ++num_non_zero_divergent_filter_fraction_; | |
| 375 } | |
| 376 } else { | |
| 377 DLOG(WARNING) << "Get echo cancellation metrics failed."; | |
| 378 } | |
| 379 ++num_divergent_filter_fraction_; | |
| 380 chunks_for_divergent_filter_stats_ = 0; | |
| 381 } | |
| 382 | |
| 383 void EchoInformation::ReportAndResetAecDivergentFilterStats() { | |
| 384 if (num_divergent_filter_fraction_ == 0) | |
| 385 return; | |
| 386 | |
| 387 int non_zero_percent = 100 * num_non_zero_divergent_filter_fraction_ / | |
| 388 num_divergent_filter_fraction_; | |
| 389 UMA_HISTOGRAM_PERCENTAGE("WebRTC.AecDivergentFilterNonZeroPeriods", | |
| 390 non_zero_percent); | |
| 391 | |
| 392 chunks_for_divergent_filter_stats_ = 0; | |
| 393 num_non_zero_divergent_filter_fraction_ = 0; | |
| 394 num_divergent_filter_fraction_ = 0; | |
| 395 } | |
| 396 | |
| 348 void EnableEchoCancellation(AudioProcessing* audio_processing) { | 397 void EnableEchoCancellation(AudioProcessing* audio_processing) { |
| 349 #if defined(OS_ANDROID) | 398 #if defined(OS_ANDROID) |
| 350 // Mobile devices are using AECM. | 399 // Mobile devices are using AECM. |
| 351 CHECK_EQ(0, audio_processing->echo_control_mobile()->set_routing_mode( | 400 CHECK_EQ(0, audio_processing->echo_control_mobile()->set_routing_mode( |
| 352 webrtc::EchoControlMobile::kSpeakerphone)); | 401 webrtc::EchoControlMobile::kSpeakerphone)); |
| 353 CHECK_EQ(0, audio_processing->echo_control_mobile()->Enable(true)); | 402 CHECK_EQ(0, audio_processing->echo_control_mobile()->Enable(true)); |
| 354 return; | 403 return; |
| 355 #endif | 404 #endif |
| 356 int err = audio_processing->echo_cancellation()->set_suppression_level( | 405 int err = audio_processing->echo_cancellation()->set_suppression_level( |
| 357 webrtc::EchoCancellation::kHighSuppression); | 406 webrtc::EchoCancellation::kHighSuppression); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 466 | 515 |
| 467 // Give preference to the audio constraint over the device-supplied mic | 516 // Give preference to the audio constraint over the device-supplied mic |
| 468 // positions. This is mainly for testing purposes. | 517 // positions. This is mainly for testing purposes. |
| 469 return WebrtcPointsFromMediaPoints( | 518 return WebrtcPointsFromMediaPoints( |
| 470 constraints_geometry.empty() | 519 constraints_geometry.empty() |
| 471 ? input_params.mic_positions | 520 ? input_params.mic_positions |
| 472 : media::ParsePointsFromString(constraints_geometry)); | 521 : media::ParsePointsFromString(constraints_geometry)); |
| 473 } | 522 } |
| 474 | 523 |
| 475 } // namespace content | 524 } // namespace content |
| OLD | NEW |