Add fallback histograms for VideoDecoderSoftwareFallbackWrapper

Track the number of samples that are decoded until a fallback to
software decoder happens.

Bug: chromium:1061376
Change-Id: Ida3ae94034ec83a6d28001cb7be343b8b99b99c3
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/170468
Commit-Queue: Johannes Kron <kron@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30814}
diff --git a/api/video_codecs/BUILD.gn b/api/video_codecs/BUILD.gn
index 5475af9..cb5ede0 100644
--- a/api/video_codecs/BUILD.gn
+++ b/api/video_codecs/BUILD.gn
@@ -143,6 +143,7 @@
     "../../rtc_base:rtc_base_approved",
     "../../rtc_base/system:rtc_export",
     "../../system_wrappers:field_trial",
+    "../../system_wrappers:metrics",
     "../video:encoded_image",
     "../video:video_bitrate_allocation",
     "../video:video_frame",
diff --git a/api/video_codecs/video_decoder_software_fallback_wrapper.cc b/api/video_codecs/video_decoder_software_fallback_wrapper.cc
index 3987db6..f78d9b8 100644
--- a/api/video_codecs/video_decoder_software_fallback_wrapper.cc
+++ b/api/video_codecs/video_decoder_software_fallback_wrapper.cc
@@ -24,6 +24,7 @@
 #include "rtc_base/logging.h"
 #include "rtc_base/trace_event.h"
 #include "system_wrappers/include/field_trial.h"
+#include "system_wrappers/include/metrics.h"
 
 namespace webrtc {
 
@@ -53,6 +54,8 @@
 
  private:
   bool InitFallbackDecoder();
+  void UpdateFallbackDecoderHistograms();
+
   int32_t InitHwDecoder();
 
   VideoDecoder& active_decoder() const;
@@ -70,6 +73,7 @@
   const std::unique_ptr<VideoDecoder> fallback_decoder_;
   const std::string fallback_implementation_name_;
   DecodedImageCallback* callback_;
+  int32_t hw_decoded_frames_since_last_fallback_;
 };
 
 VideoDecoderSoftwareFallbackWrapper::VideoDecoderSoftwareFallbackWrapper(
@@ -81,7 +85,8 @@
       fallback_implementation_name_(
           std::string(fallback_decoder_->ImplementationName()) +
           " (fallback from: " + hw_decoder_->ImplementationName() + ")"),
-      callback_(nullptr) {}
+      callback_(nullptr),
+      hw_decoded_frames_since_last_fallback_(0) {}
 VideoDecoderSoftwareFallbackWrapper::~VideoDecoderSoftwareFallbackWrapper() =
     default;
 
@@ -134,6 +139,8 @@
     return false;
   }
 
+  UpdateFallbackDecoderHistograms();
+
   if (decoder_type_ == DecoderType::kHardware) {
     hw_decoder_->Release();
   }
@@ -144,6 +151,39 @@
   return true;
 }
 
+void VideoDecoderSoftwareFallbackWrapper::UpdateFallbackDecoderHistograms() {
+  const std::string kFallbackHistogramsUmaPrefix =
+      "WebRTC.Video.HardwareDecodedFramesBetweenSoftwareFallbacks.";
+  // Each histogram needs its own code path for this to work otherwise the
+  // histogram names will be mixed up by the optimization that takes place.
+  switch (codec_settings_.codecType) {
+    case kVideoCodecGeneric:
+      RTC_HISTOGRAM_COUNTS_100000(kFallbackHistogramsUmaPrefix + "Generic",
+                                  hw_decoded_frames_since_last_fallback_);
+      break;
+    case kVideoCodecVP8:
+      RTC_HISTOGRAM_COUNTS_100000(kFallbackHistogramsUmaPrefix + "Vp8",
+                                  hw_decoded_frames_since_last_fallback_);
+      break;
+    case kVideoCodecVP9:
+      RTC_HISTOGRAM_COUNTS_100000(kFallbackHistogramsUmaPrefix + "Vp9",
+                                  hw_decoded_frames_since_last_fallback_);
+      break;
+    case kVideoCodecAV1:
+      RTC_HISTOGRAM_COUNTS_100000(kFallbackHistogramsUmaPrefix + "Av1",
+                                  hw_decoded_frames_since_last_fallback_);
+      break;
+    case kVideoCodecH264:
+      RTC_HISTOGRAM_COUNTS_100000(kFallbackHistogramsUmaPrefix + "H264",
+                                  hw_decoded_frames_since_last_fallback_);
+      break;
+    case kVideoCodecMultiplex:
+      RTC_HISTOGRAM_COUNTS_100000(kFallbackHistogramsUmaPrefix + "Multiplex",
+                                  hw_decoded_frames_since_last_fallback_);
+      break;
+  }
+}
+
 int32_t VideoDecoderSoftwareFallbackWrapper::Decode(
     const EncodedImage& input_image,
     bool missing_frames,
@@ -156,6 +196,9 @@
       int32_t ret = WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
       ret = hw_decoder_->Decode(input_image, missing_frames, render_time_ms);
       if (ret != WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE) {
+        if (ret == WEBRTC_VIDEO_CODEC_OK) {
+          ++hw_decoded_frames_since_last_fallback_;
+        }
         return ret;
       }