Add per frame decode time histograms for 4k/HD and VP9/H264
Add new histograms
WebRTC.Video.DecodeTimePerFrameInMs.[codec].[resolution].[decoder]
These histograms are more explicit than the existing histogram
WebRTC.VideoDecodTimeMs, since they allow to see performance per
codec/resolution/decoder and also contain per frame statistics instead
of an average decode time.
There's a killswitch, WebRTC-DecodeTimeHistogramsKillSwitch, that can be
used to disable the histograms.
Bug: chromium:1007526
Change-Id: I9f75127b4bc5341e9f406c64ed91164564290b26
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/157881
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Commit-Queue: Johannes Kron <kron@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29572}
diff --git a/video/receive_statistics_proxy.cc b/video/receive_statistics_proxy.cc
index 42ab7e1..d8bde94 100644
--- a/video/receive_statistics_proxy.cc
+++ b/video/receive_statistics_proxy.cc
@@ -20,6 +20,7 @@
#include "rtc_base/strings/string_builder.h"
#include "rtc_base/time_utils.h"
#include "system_wrappers/include/clock.h"
+#include "system_wrappers/include/field_trial.h"
#include "system_wrappers/include/metrics.h"
namespace webrtc {
@@ -85,6 +86,8 @@
: clock_(clock),
config_(*config),
start_ms_(clock->TimeInMilliseconds()),
+ enable_decode_time_histograms_(
+ !field_trial::IsEnabled("WebRTC-DecodeTimeHistogramsKillSwitch")),
last_sample_time_(clock->TimeInMilliseconds()),
fps_threshold_(kLowFpsThreshold,
kHighFpsThreshold,
@@ -553,6 +556,61 @@
stats_.network_frame_rate = static_cast<int>(framerate);
}
+void ReceiveStatisticsProxy::UpdateDecodeTimeHistograms(
+ int width,
+ int height,
+ int decode_time_ms) const {
+ bool is_4k = (width == 3840 || width == 4096) && height == 2160;
+ bool is_hd = width == 1920 && height == 1080;
+ // Only update histograms for 4k/HD and VP9/H264.
+ if ((is_4k || is_hd) && (last_codec_type_ == kVideoCodecVP9 ||
+ last_codec_type_ == kVideoCodecH264)) {
+ const std::string kDecodeTimeUmaPrefix =
+ "WebRTC.Video.DecodeTimePerFrameInMs.";
+
+ // Each histogram needs its own line for it to not be reused in the wrong
+ // way when the format changes.
+ if (last_codec_type_ == kVideoCodecVP9) {
+ bool is_sw_decoder =
+ stats_.decoder_implementation_name.compare(0, 6, "libvpx") == 0;
+ if (is_4k) {
+ if (is_sw_decoder)
+ RTC_HISTOGRAM_COUNTS_1000(kDecodeTimeUmaPrefix + "Vp9.4k.Sw",
+ decode_time_ms);
+ else
+ RTC_HISTOGRAM_COUNTS_1000(kDecodeTimeUmaPrefix + "Vp9.4k.Hw",
+ decode_time_ms);
+ } else {
+ if (is_sw_decoder)
+ RTC_HISTOGRAM_COUNTS_1000(kDecodeTimeUmaPrefix + "Vp9.Hd.Sw",
+ decode_time_ms);
+ else
+ RTC_HISTOGRAM_COUNTS_1000(kDecodeTimeUmaPrefix + "Vp9.Hd.Hw",
+ decode_time_ms);
+ }
+ } else {
+ bool is_sw_decoder =
+ stats_.decoder_implementation_name.compare(0, 6, "FFmpeg") == 0;
+ if (is_4k) {
+ if (is_sw_decoder)
+ RTC_HISTOGRAM_COUNTS_1000(kDecodeTimeUmaPrefix + "H264.4k.Sw",
+ decode_time_ms);
+ else
+ RTC_HISTOGRAM_COUNTS_1000(kDecodeTimeUmaPrefix + "H264.4k.Hw",
+ decode_time_ms);
+
+ } else {
+ if (is_sw_decoder)
+ RTC_HISTOGRAM_COUNTS_1000(kDecodeTimeUmaPrefix + "H264.Hd.Sw",
+ decode_time_ms);
+ else
+ RTC_HISTOGRAM_COUNTS_1000(kDecodeTimeUmaPrefix + "H264.Hd.Hw",
+ decode_time_ms);
+ }
+ }
+ }
+}
+
VideoReceiveStream::Stats ReceiveStatisticsProxy::GetStats() const {
rtc::CritScope lock(&crit_);
// Get current frame rates here, as only updating them on new frames prevents
@@ -697,6 +755,10 @@
decode_time_counter_.Add(decode_time_ms);
stats_.decode_ms = decode_time_ms;
stats_.total_decode_time_ms += decode_time_ms;
+ if (enable_decode_time_histograms_) {
+ UpdateDecodeTimeHistograms(frame.width(), frame.height(), decode_time_ms);
+ }
+
last_content_type_ = content_type;
decode_fps_estimator_.Update(1, now_ms);
if (last_decoded_frame_time_ms_) {