Add harmonic frame rate metric to the PC level test framework

Bug: webrtc:11348
Change-Id: I4dd0cabbaee2d4b5e2dd4fa4398b3d7c0beaa3eb
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/168401
Reviewed-by: Christoffer Rodbro <crodbro@webrtc.org>
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30492}
diff --git a/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc b/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc
index 13db2b4..d2b25a8 100644
--- a/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc
+++ b/test/pc/e2e/analyzer/video/default_video_quality_analyzer.cc
@@ -635,6 +635,23 @@
     const FrameCounters& frame_counters) {
   using ::webrtc::test::ImproveDirection;
 
+  double sum_squared_interframe_delays_secs = 0;
+  for (const double interframe_delay_ms :
+       stats.time_between_rendered_frames_ms.GetSamples()) {
+    const double interframe_delays_secs = interframe_delay_ms / 1000.0;
+    // Sum of squared inter frame intervals is used to calculate the harmonic
+    // frame rate metric. The metric aims to reflect overall experience related
+    // to smoothness of video playback and includes both freezes and pauses.
+    sum_squared_interframe_delays_secs +=
+        interframe_delays_secs * interframe_delays_secs;
+  }
+  double harmonic_framerate_fps = 0;
+  if (sum_squared_interframe_delays_secs > 0.0) {
+    TimeDelta video_duration = Now() - start_time_;
+    harmonic_framerate_fps =
+        video_duration.seconds() / sum_squared_interframe_delays_secs;
+  }
+
   ReportResult("psnr", test_case_name, stats.psnr, "dB",
                ImproveDirection::kBiggerIsBetter);
   ReportResult("ssim", test_case_name, stats.ssim, "unitless",
@@ -647,11 +664,14 @@
   ReportResult("time_between_rendered_frames", test_case_name,
                stats.time_between_rendered_frames_ms, "ms",
                ImproveDirection::kSmallerIsBetter);
+  test::PrintResult("harmonic_framerate", "", test_case_name,
+                    harmonic_framerate_fps, "Hz", /*important=*/false,
+                    ImproveDirection::kBiggerIsBetter);
   test::PrintResult("encode_frame_rate", "", test_case_name,
                     stats.encode_frame_rate.IsEmpty()
                         ? 0
                         : stats.encode_frame_rate.GetEventsPerSecond(),
-                    "fps", /*important=*/false,
+                    "Hz", /*important=*/false,
                     ImproveDirection::kBiggerIsBetter);
   ReportResult("encode_time", test_case_name, stats.encode_time_ms, "ms",
                ImproveDirection::kSmallerIsBetter);
diff --git a/test/pc/e2e/analyzer/video/default_video_quality_analyzer.h b/test/pc/e2e/analyzer/video/default_video_quality_analyzer.h
index d99e6ac..736cd9d 100644
--- a/test/pc/e2e/analyzer/video/default_video_quality_analyzer.h
+++ b/test/pc/e2e/analyzer/video/default_video_quality_analyzer.h
@@ -242,9 +242,10 @@
   void ReportResults();
   static void ReportVideoBweResults(const std::string& test_case_name,
                                     const VideoBweStats& video_bwe_stats);
-  static void ReportResults(const std::string& test_case_name,
-                            const StreamStats& stats,
-                            const FrameCounters& frame_counters);
+  void ReportResults(const std::string& test_case_name,
+                     const StreamStats& stats,
+                     const FrameCounters& frame_counters)
+      RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_);
   // Report result for single metric for specified stream.
   static void ReportResult(const std::string& metric_name,
                            const std::string& test_case_name,