Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 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 |
| 11 #include "video/send_statistics_proxy.h" | 11 #include "video/send_statistics_proxy.h" |
| 12 | 12 |
| 13 #include <algorithm> | 13 #include <algorithm> |
| 14 #include <cmath> | 14 #include <cmath> |
| 15 #include <map> | 15 #include <map> |
| 16 #include <vector> | 16 #include <vector> |
| 17 | 17 |
| 18 #include "common_types.h" | 18 #include "common_types.h" |
|
mbonadei
2017/09/15 11:36:34
Please change this line with:
#include "common_typ
åsapersson
2017/09/15 12:09:41
Done.
| |
| 19 #include "modules/video_coding/include/video_codec_interface.h" | 19 #include "modules/video_coding/include/video_codec_interface.h" |
| 20 #include "rtc_base/checks.h" | 20 #include "rtc_base/checks.h" |
| 21 #include "rtc_base/logging.h" | 21 #include "rtc_base/logging.h" |
| 22 #include "system_wrappers/include/field_trial.h" | |
| 22 #include "system_wrappers/include/metrics.h" | 23 #include "system_wrappers/include/metrics.h" |
| 23 | 24 |
| 24 namespace webrtc { | 25 namespace webrtc { |
| 25 namespace { | 26 namespace { |
| 26 const float kEncodeTimeWeigthFactor = 0.5f; | 27 const float kEncodeTimeWeigthFactor = 0.5f; |
| 27 | 28 |
| 29 const char kVp8ForcedFallbackEncoderFieldTrial[] = | |
| 30 "WebRTC-VP8-Forced-Fallback-Encoder"; | |
| 31 const char kVp8SwCodecName[] = "libvpx"; | |
| 32 | |
| 28 // Used by histograms. Values of entries should not be changed. | 33 // Used by histograms. Values of entries should not be changed. |
| 29 enum HistogramCodecType { | 34 enum HistogramCodecType { |
| 30 kVideoUnknown = 0, | 35 kVideoUnknown = 0, |
| 31 kVideoVp8 = 1, | 36 kVideoVp8 = 1, |
| 32 kVideoVp9 = 2, | 37 kVideoVp9 = 2, |
| 33 kVideoH264 = 3, | 38 kVideoH264 = 3, |
| 34 kVideoMax = 64, | 39 kVideoMax = 64, |
| 35 }; | 40 }; |
| 36 | 41 |
| 37 const char* kRealtimePrefix = "WebRTC.Video."; | 42 const char* kRealtimePrefix = "WebRTC.Video."; |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 61 default: | 66 default: |
| 62 return kVideoUnknown; | 67 return kVideoUnknown; |
| 63 } | 68 } |
| 64 } | 69 } |
| 65 | 70 |
| 66 void UpdateCodecTypeHistogram(const std::string& payload_name) { | 71 void UpdateCodecTypeHistogram(const std::string& payload_name) { |
| 67 RTC_HISTOGRAM_ENUMERATION("WebRTC.Video.Encoder.CodecType", | 72 RTC_HISTOGRAM_ENUMERATION("WebRTC.Video.Encoder.CodecType", |
| 68 PayloadNameToHistogramCodecType(payload_name), | 73 PayloadNameToHistogramCodecType(payload_name), |
| 69 kVideoMax); | 74 kVideoMax); |
| 70 } | 75 } |
| 76 | |
| 77 bool IsForcedFallbackPossible(const CodecSpecificInfo* codec_info) { | |
| 78 return codec_info->codecType == kVideoCodecVP8 && | |
| 79 codec_info->codecSpecific.VP8.simulcastIdx == 0 && | |
| 80 (codec_info->codecSpecific.VP8.temporalIdx == 0 || | |
| 81 codec_info->codecSpecific.VP8.temporalIdx == kNoTemporalIdx); | |
| 82 } | |
| 83 | |
| 84 rtc::Optional<int> GetFallbackIntervalFromFieldTrial() { | |
| 85 if (!webrtc::field_trial::IsEnabled(kVp8ForcedFallbackEncoderFieldTrial)) | |
| 86 return rtc::Optional<int>(); | |
| 87 | |
| 88 std::string group = | |
| 89 webrtc::field_trial::FindFullName(kVp8ForcedFallbackEncoderFieldTrial); | |
| 90 if (group.empty()) | |
| 91 return rtc::Optional<int>(); | |
| 92 | |
| 93 int low_kbps; | |
| 94 int high_kbps; | |
| 95 int min_low_ms; | |
| 96 int min_pixels; | |
| 97 if (sscanf(group.c_str(), "Enabled-%d,%d,%d,%d", &low_kbps, &high_kbps, | |
| 98 &min_low_ms, &min_pixels) != 4) { | |
| 99 return rtc::Optional<int>(); | |
| 100 } | |
| 101 | |
| 102 if (min_low_ms <= 0 || min_pixels <= 0 || low_kbps <= 0 || | |
| 103 high_kbps <= low_kbps) { | |
| 104 return rtc::Optional<int>(); | |
| 105 } | |
| 106 return rtc::Optional<int>(min_low_ms); | |
| 107 } | |
| 71 } // namespace | 108 } // namespace |
| 72 | 109 |
| 73 | 110 |
| 74 const int SendStatisticsProxy::kStatsTimeoutMs = 5000; | 111 const int SendStatisticsProxy::kStatsTimeoutMs = 5000; |
| 75 | 112 |
| 76 SendStatisticsProxy::SendStatisticsProxy( | 113 SendStatisticsProxy::SendStatisticsProxy( |
| 77 Clock* clock, | 114 Clock* clock, |
| 78 const VideoSendStream::Config& config, | 115 const VideoSendStream::Config& config, |
| 79 VideoEncoderConfig::ContentType content_type) | 116 VideoEncoderConfig::ContentType content_type) |
| 80 : clock_(clock), | 117 : clock_(clock), |
| 81 payload_name_(config.encoder_settings.payload_name), | 118 payload_name_(config.encoder_settings.payload_name), |
| 82 rtp_config_(config.rtp), | 119 rtp_config_(config.rtp), |
| 120 min_first_fallback_interval_ms_(GetFallbackIntervalFromFieldTrial()), | |
| 83 content_type_(content_type), | 121 content_type_(content_type), |
| 84 start_ms_(clock->TimeInMilliseconds()), | 122 start_ms_(clock->TimeInMilliseconds()), |
| 85 last_sent_frame_timestamp_(0), | 123 last_sent_frame_timestamp_(0), |
| 86 encode_time_(kEncodeTimeWeigthFactor), | 124 encode_time_(kEncodeTimeWeigthFactor), |
| 87 quality_downscales_(-1), | 125 quality_downscales_(-1), |
| 88 cpu_downscales_(-1), | 126 cpu_downscales_(-1), |
| 89 uma_container_( | 127 uma_container_( |
| 90 new UmaSamplesContainer(GetUmaPrefix(content_type_), stats_, clock)) { | 128 new UmaSamplesContainer(GetUmaPrefix(content_type_), stats_, clock)) { |
| 91 } | 129 } |
| 92 | 130 |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 403 paused_time_counter_.Percent(metrics::kMinRunTimeInSeconds * 1000); | 441 paused_time_counter_.Percent(metrics::kMinRunTimeInSeconds * 1000); |
| 404 if (paused_time_percent != -1) { | 442 if (paused_time_percent != -1) { |
| 405 RTC_HISTOGRAMS_PERCENTAGE(kIndex, uma_prefix_ + "PausedTimeInPercent", | 443 RTC_HISTOGRAMS_PERCENTAGE(kIndex, uma_prefix_ + "PausedTimeInPercent", |
| 406 paused_time_percent); | 444 paused_time_percent); |
| 407 LOG(LS_INFO) << uma_prefix_ << "PausedTimeInPercent " | 445 LOG(LS_INFO) << uma_prefix_ << "PausedTimeInPercent " |
| 408 << paused_time_percent; | 446 << paused_time_percent; |
| 409 } | 447 } |
| 410 } | 448 } |
| 411 } | 449 } |
| 412 | 450 |
| 451 if (fallback_info_.is_possible) { | |
| 452 // Double interval since there is some time before fallback may occur. | |
| 453 const int kMinRunTimeMs = 2 * metrics::kMinRunTimeInSeconds * 1000; | |
| 454 int64_t elapsed_ms = fallback_info_.elapsed_ms; | |
| 455 int fallback_time_percent = fallback_active_counter_.Percent(kMinRunTimeMs); | |
| 456 if (fallback_time_percent != -1 && elapsed_ms >= kMinRunTimeMs) { | |
| 457 RTC_HISTOGRAMS_PERCENTAGE( | |
| 458 kIndex, uma_prefix_ + "Encoder.ForcedSwFallbackTimeInPercent.Vp8", | |
| 459 fallback_time_percent); | |
| 460 RTC_HISTOGRAMS_COUNTS_100( | |
| 461 kIndex, uma_prefix_ + "Encoder.ForcedSwFallbackChangesPerMinute.Vp8", | |
| 462 fallback_info_.on_off_events * 60 / (elapsed_ms / 1000)); | |
| 463 } | |
| 464 } | |
| 465 | |
| 413 AggregatedStats total_bytes_per_sec = total_byte_counter_.GetStats(); | 466 AggregatedStats total_bytes_per_sec = total_byte_counter_.GetStats(); |
| 414 if (total_bytes_per_sec.num_samples > kMinRequiredPeriodicSamples) { | 467 if (total_bytes_per_sec.num_samples > kMinRequiredPeriodicSamples) { |
| 415 RTC_HISTOGRAMS_COUNTS_10000(kIndex, uma_prefix_ + "BitrateSentInKbps", | 468 RTC_HISTOGRAMS_COUNTS_10000(kIndex, uma_prefix_ + "BitrateSentInKbps", |
| 416 total_bytes_per_sec.average * 8 / 1000); | 469 total_bytes_per_sec.average * 8 / 1000); |
| 417 LOG(LS_INFO) << uma_prefix_ << "BitrateSentInBps, " | 470 LOG(LS_INFO) << uma_prefix_ << "BitrateSentInBps, " |
| 418 << total_bytes_per_sec.ToStringWithMultiplier(8); | 471 << total_bytes_per_sec.ToStringWithMultiplier(8); |
| 419 } | 472 } |
| 420 AggregatedStats media_bytes_per_sec = media_byte_counter_.GetStats(); | 473 AggregatedStats media_bytes_per_sec = media_byte_counter_.GetStats(); |
| 421 if (media_bytes_per_sec.num_samples > kMinRequiredPeriodicSamples) { | 474 if (media_bytes_per_sec.num_samples > kMinRequiredPeriodicSamples) { |
| 422 RTC_HISTOGRAMS_COUNTS_10000(kIndex, uma_prefix_ + "MediaBitrateSentInKbps", | 475 RTC_HISTOGRAMS_COUNTS_10000(kIndex, uma_prefix_ + "MediaBitrateSentInKbps", |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 613 | 666 |
| 614 // Check if video is paused/resumed. | 667 // Check if video is paused/resumed. |
| 615 uma_container_->target_rate_updates_.last_paused_or_resumed = | 668 uma_container_->target_rate_updates_.last_paused_or_resumed = |
| 616 (bitrate_bps == 0) != was_paused; | 669 (bitrate_bps == 0) != was_paused; |
| 617 } | 670 } |
| 618 uma_container_->target_rate_updates_.last_ms = now; | 671 uma_container_->target_rate_updates_.last_ms = now; |
| 619 | 672 |
| 620 stats_.target_media_bitrate_bps = bitrate_bps; | 673 stats_.target_media_bitrate_bps = bitrate_bps; |
| 621 } | 674 } |
| 622 | 675 |
| 676 void SendStatisticsProxy::UpdateEncoderFallbackStats( | |
| 677 const CodecSpecificInfo* codec_info) { | |
| 678 if (!min_first_fallback_interval_ms_ || | |
| 679 !uma_container_->fallback_info_.is_possible) { | |
| 680 return; | |
| 681 } | |
| 682 | |
| 683 if (!IsForcedFallbackPossible(codec_info)) { | |
| 684 uma_container_->fallback_info_.is_possible = false; | |
| 685 return; | |
| 686 } | |
| 687 | |
| 688 FallbackEncoderInfo* fallback_info = &uma_container_->fallback_info_; | |
| 689 | |
| 690 const int64_t now_ms = clock_->TimeInMilliseconds(); | |
| 691 bool is_active = fallback_info->is_active; | |
| 692 if (codec_info->codec_name != stats_.encoder_implementation_name) { | |
| 693 // Implementation changed. | |
| 694 is_active = strcmp(codec_info->codec_name, kVp8SwCodecName) == 0; | |
| 695 if (!is_active && stats_.encoder_implementation_name != kVp8SwCodecName) { | |
| 696 // First or not a VP8 SW change, update stats on next call. | |
| 697 return; | |
| 698 } | |
| 699 if (is_active && fallback_info->on_off_events == 0) { | |
| 700 // The minimum set time should have passed for the first fallback (else | |
| 701 // skip to avoid fallback due to failure). | |
| 702 int64_t elapsed_ms = fallback_info->elapsed_ms; | |
| 703 if (fallback_info->last_update_ms) | |
| 704 elapsed_ms += now_ms - *(fallback_info->last_update_ms); | |
| 705 if (elapsed_ms < *min_first_fallback_interval_ms_) { | |
| 706 fallback_info->is_possible = false; | |
| 707 return; | |
| 708 } | |
| 709 } | |
| 710 ++fallback_info->on_off_events; | |
| 711 } | |
| 712 | |
| 713 if (fallback_info->last_update_ms) { | |
| 714 int64_t diff_ms = now_ms - *(fallback_info->last_update_ms); | |
| 715 // If the time diff since last update is greater than |max_frame_diff_ms|, | |
| 716 // video is considered paused/muted and the change is not included. | |
| 717 if (diff_ms < fallback_info->max_frame_diff_ms) { | |
| 718 uma_container_->fallback_active_counter_.Add(fallback_info->is_active, | |
| 719 diff_ms); | |
| 720 fallback_info->elapsed_ms += diff_ms; | |
| 721 } | |
| 722 } | |
| 723 fallback_info->is_active = is_active; | |
| 724 fallback_info->last_update_ms.emplace(now_ms); | |
| 725 } | |
| 726 | |
| 623 void SendStatisticsProxy::OnSendEncodedImage( | 727 void SendStatisticsProxy::OnSendEncodedImage( |
| 624 const EncodedImage& encoded_image, | 728 const EncodedImage& encoded_image, |
| 625 const CodecSpecificInfo* codec_info) { | 729 const CodecSpecificInfo* codec_info) { |
| 626 size_t simulcast_idx = 0; | 730 size_t simulcast_idx = 0; |
| 627 | 731 |
| 628 rtc::CritScope lock(&crit_); | 732 rtc::CritScope lock(&crit_); |
| 629 ++stats_.frames_encoded; | 733 ++stats_.frames_encoded; |
| 630 if (codec_info) { | 734 if (codec_info) { |
| 631 if (codec_info->codecType == kVideoCodecVP8) { | 735 if (codec_info->codecType == kVideoCodecVP8) { |
| 632 simulcast_idx = codec_info->codecSpecific.VP8.simulcastIdx; | 736 simulcast_idx = codec_info->codecSpecific.VP8.simulcastIdx; |
| 633 } else if (codec_info->codecType == kVideoCodecGeneric) { | 737 } else if (codec_info->codecType == kVideoCodecGeneric) { |
| 634 simulcast_idx = codec_info->codecSpecific.generic.simulcast_idx; | 738 simulcast_idx = codec_info->codecSpecific.generic.simulcast_idx; |
| 635 } | 739 } |
| 636 if (codec_info->codec_name) { | 740 if (codec_info->codec_name) { |
| 741 UpdateEncoderFallbackStats(codec_info); | |
| 637 stats_.encoder_implementation_name = codec_info->codec_name; | 742 stats_.encoder_implementation_name = codec_info->codec_name; |
| 638 } | 743 } |
| 639 } | 744 } |
| 640 | 745 |
| 641 if (simulcast_idx >= rtp_config_.ssrcs.size()) { | 746 if (simulcast_idx >= rtp_config_.ssrcs.size()) { |
| 642 LOG(LS_ERROR) << "Encoded image outside simulcast range (" << simulcast_idx | 747 LOG(LS_ERROR) << "Encoded image outside simulcast range (" << simulcast_idx |
| 643 << " >= " << rtp_config_.ssrcs.size() << ")."; | 748 << " >= " << rtp_config_.ssrcs.size() << ")."; |
| 644 return; | 749 return; |
| 645 } | 750 } |
| 646 uint32_t ssrc = rtp_config_.ssrcs[simulcast_idx]; | 751 uint32_t ssrc = rtp_config_.ssrcs[simulcast_idx]; |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 935 } | 1040 } |
| 936 | 1041 |
| 937 int SendStatisticsProxy::BoolSampleCounter::Fraction( | 1042 int SendStatisticsProxy::BoolSampleCounter::Fraction( |
| 938 int64_t min_required_samples, | 1043 int64_t min_required_samples, |
| 939 float multiplier) const { | 1044 float multiplier) const { |
| 940 if (num_samples < min_required_samples || num_samples == 0) | 1045 if (num_samples < min_required_samples || num_samples == 0) |
| 941 return -1; | 1046 return -1; |
| 942 return static_cast<int>((sum * multiplier / num_samples) + 0.5f); | 1047 return static_cast<int>((sum * multiplier / num_samples) + 0.5f); |
| 943 } | 1048 } |
| 944 } // namespace webrtc | 1049 } // namespace webrtc |
| OLD | NEW |