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

Side by Side Diff: 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
« no previous file with comments | « video/send_statistics_proxy.h ('k') | video/send_statistics_proxy_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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" // NOLINT(build/include)
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
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 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
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
OLDNEW
« no previous file with comments | « video/send_statistics_proxy.h ('k') | video/send_statistics_proxy_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698