OLD | NEW |
---|---|
1 /* | 1 /* |
brandtr
2017/09/14 12:30:11
It looks like this member variable is unused: http
åsapersson
2017/09/14 14:41:44
Ok, will remove in a separate CL.
| |
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 "webrtc/video/send_statistics_proxy.h" | 11 #include "webrtc/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 "webrtc/common_types.h" | 18 #include "webrtc/common_types.h" |
19 #include "webrtc/modules/video_coding/include/video_codec_interface.h" | 19 #include "webrtc/modules/video_coding/include/video_codec_interface.h" |
20 #include "webrtc/rtc_base/checks.h" | 20 #include "webrtc/rtc_base/checks.h" |
21 #include "webrtc/rtc_base/logging.h" | 21 #include "webrtc/rtc_base/logging.h" |
22 #include "webrtc/system_wrappers/include/field_trial.h" | |
22 #include "webrtc/system_wrappers/include/metrics.h" | 23 #include "webrtc/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 FallbackEncoderInfo* fallback_info) { | |
679 if (!min_first_fallback_interval_ms_ || !fallback_info->is_possible) { | |
680 return; | |
681 } | |
682 | |
683 if (!IsForcedFallbackPossible(codec_info)) { | |
684 fallback_info->is_possible = false; | |
685 return; | |
686 } | |
687 | |
688 const int64_t now_ms = clock_->TimeInMilliseconds(); | |
689 bool is_active = fallback_info->is_active; | |
690 if (codec_info->codec_name != stats_.encoder_implementation_name) { | |
691 // Implementation changed. | |
692 is_active = strcmp(codec_info->codec_name, kVp8SwCodecName) == 0; | |
693 if (!is_active && stats_.encoder_implementation_name != kVp8SwCodecName) { | |
694 // First or not a VP8 SW change, update stats on next call. | |
695 return; | |
696 } | |
697 if (is_active && fallback_info->on_off_events == 0) { | |
698 // The minimum set time should have passed for the first fallback. | |
brandtr
2017/09/14 12:30:11
Can you extend this comment to explain why it's im
åsapersson
2017/09/14 14:41:43
Done.
| |
699 int64_t elapsed_ms = fallback_info->elapsed_ms; | |
700 if (fallback_info->last_update_ms) | |
701 elapsed_ms += now_ms - *(fallback_info->last_update_ms); | |
702 if (elapsed_ms < *min_first_fallback_interval_ms_) { | |
703 fallback_info->is_possible = false; | |
704 return; | |
705 } | |
706 } | |
707 ++fallback_info->on_off_events; | |
708 } | |
709 | |
710 if (fallback_info->last_update_ms) { | |
711 int64_t diff_ms = now_ms - *(fallback_info->last_update_ms); | |
712 // If the time diff since last update is greater than |max_frame_diff_ms|, | |
713 // video is considered paused and the change is not included. | |
brandtr
2017/09/14 12:30:11
Is this to avoid recording real failures, where it
åsapersson
2017/09/14 14:41:43
Updated comment a bit, it is to exclude time when
| |
714 if (diff_ms < fallback_info->max_frame_diff_ms) { | |
715 uma_container_->fallback_active_counter_.Add(fallback_info->is_active, | |
716 diff_ms); | |
717 fallback_info->elapsed_ms += diff_ms; | |
718 } | |
719 } | |
720 fallback_info->is_active = is_active; | |
721 fallback_info->last_update_ms.emplace(now_ms); | |
722 } | |
723 | |
623 void SendStatisticsProxy::OnSendEncodedImage( | 724 void SendStatisticsProxy::OnSendEncodedImage( |
624 const EncodedImage& encoded_image, | 725 const EncodedImage& encoded_image, |
625 const CodecSpecificInfo* codec_info) { | 726 const CodecSpecificInfo* codec_info) { |
626 size_t simulcast_idx = 0; | 727 size_t simulcast_idx = 0; |
627 | 728 |
628 rtc::CritScope lock(&crit_); | 729 rtc::CritScope lock(&crit_); |
629 ++stats_.frames_encoded; | 730 ++stats_.frames_encoded; |
630 if (codec_info) { | 731 if (codec_info) { |
631 if (codec_info->codecType == kVideoCodecVP8) { | 732 if (codec_info->codecType == kVideoCodecVP8) { |
632 simulcast_idx = codec_info->codecSpecific.VP8.simulcastIdx; | 733 simulcast_idx = codec_info->codecSpecific.VP8.simulcastIdx; |
633 } else if (codec_info->codecType == kVideoCodecGeneric) { | 734 } else if (codec_info->codecType == kVideoCodecGeneric) { |
634 simulcast_idx = codec_info->codecSpecific.generic.simulcast_idx; | 735 simulcast_idx = codec_info->codecSpecific.generic.simulcast_idx; |
635 } | 736 } |
636 if (codec_info->codec_name) { | 737 if (codec_info->codec_name) { |
738 UpdateEncoderFallbackStats(codec_info, &uma_container_->fallback_info_); | |
brandtr
2017/09/14 12:30:12
Is there a benefit to passing in |fallback_info_|
åsapersson
2017/09/14 14:41:43
No, removed.
| |
637 stats_.encoder_implementation_name = codec_info->codec_name; | 739 stats_.encoder_implementation_name = codec_info->codec_name; |
638 } | 740 } |
639 } | 741 } |
640 | 742 |
641 if (simulcast_idx >= rtp_config_.ssrcs.size()) { | 743 if (simulcast_idx >= rtp_config_.ssrcs.size()) { |
642 LOG(LS_ERROR) << "Encoded image outside simulcast range (" << simulcast_idx | 744 LOG(LS_ERROR) << "Encoded image outside simulcast range (" << simulcast_idx |
643 << " >= " << rtp_config_.ssrcs.size() << ")."; | 745 << " >= " << rtp_config_.ssrcs.size() << ")."; |
644 return; | 746 return; |
645 } | 747 } |
646 uint32_t ssrc = rtp_config_.ssrcs[simulcast_idx]; | 748 uint32_t ssrc = rtp_config_.ssrcs[simulcast_idx]; |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
935 } | 1037 } |
936 | 1038 |
937 int SendStatisticsProxy::BoolSampleCounter::Fraction( | 1039 int SendStatisticsProxy::BoolSampleCounter::Fraction( |
938 int64_t min_required_samples, | 1040 int64_t min_required_samples, |
939 float multiplier) const { | 1041 float multiplier) const { |
940 if (num_samples < min_required_samples || num_samples == 0) | 1042 if (num_samples < min_required_samples || num_samples == 0) |
941 return -1; | 1043 return -1; |
942 return static_cast<int>((sum * multiplier / num_samples) + 0.5f); | 1044 return static_cast<int>((sum * multiplier / num_samples) + 0.5f); |
943 } | 1045 } |
944 } // namespace webrtc | 1046 } // namespace webrtc |
OLD | NEW |