Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1196)

Side by Side Diff: webrtc/video/send_statistics_proxy.cc

Issue 3012863002: Add stats for forced software encoder fallback for VP8. (Closed)
Patch Set: Created 3 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698