Add rtt_mult_experiment to evaluate video robustness vs. latency

Bug: webrtc:9670
Change-Id: Idb4ca130bfa652b2d0bddb5bee9ed8e34c97150a
Reviewed-on: https://webrtc-review.googlesource.com/96060
Commit-Queue: Michael Horowitz <mhoro@webrtc.org>
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24457}
diff --git a/modules/video_coding/BUILD.gn b/modules/video_coding/BUILD.gn
index a81dd7c..0b76020 100644
--- a/modules/video_coding/BUILD.gn
+++ b/modules/video_coding/BUILD.gn
@@ -25,6 +25,7 @@
     "../../rtc_base:checks",
     "../../rtc_base:rtc_base_approved",
     "../../rtc_base/experiments:alr_experiment",
+    "../../rtc_base/experiments:rtt_mult_experiment",
     "../../system_wrappers:field_trial_api",
     "../../system_wrappers:system_wrappers",
     "//third_party/abseil-cpp/absl/types:optional",
@@ -169,6 +170,7 @@
     "../../rtc_base:rtc_task_queue",
     "../../rtc_base:sequenced_task_checker",
     "../../rtc_base/experiments:alr_experiment",
+    "../../rtc_base/experiments:rtt_mult_experiment",
     "../../rtc_base/system:fallthrough",
     "../../rtc_base/third_party/base64",
     "../../rtc_base/time:timestamp_extrapolator",
diff --git a/modules/video_coding/frame_buffer2.cc b/modules/video_coding/frame_buffer2.cc
index 8bb241a..377611e 100644
--- a/modules/video_coding/frame_buffer2.cc
+++ b/modules/video_coding/frame_buffer2.cc
@@ -153,10 +153,14 @@
         }
 
         float rtt_mult = protection_mode_ == kProtectionNackFEC ? 0.0 : 1.0;
+        if (RttMultExperiment::RttMultEnabled()) {
+          rtt_mult = RttMultExperiment::GetRttMultValue();
+        }
         timing_->SetJitterDelay(jitter_estimator_->GetJitterEstimate(rtt_mult));
         timing_->UpdateCurrentDelay(frame->RenderTime(), now_ms);
       } else {
-        if (webrtc::field_trial::IsEnabled("WebRTC-AddRttToPlayoutDelay"))
+        if (RttMultExperiment::RttMultEnabled() ||
+            webrtc::field_trial::IsEnabled("WebRTC-AddRttToPlayoutDelay"))
           jitter_estimator_->FrameNacked();
       }
 
diff --git a/modules/video_coding/frame_buffer2.h b/modules/video_coding/frame_buffer2.h
index bb57b83..ae84fcf 100644
--- a/modules/video_coding/frame_buffer2.h
+++ b/modules/video_coding/frame_buffer2.h
@@ -22,6 +22,7 @@
 #include "rtc_base/constructormagic.h"
 #include "rtc_base/criticalsection.h"
 #include "rtc_base/event.h"
+#include "rtc_base/experiments/rtt_mult_experiment.h"
 #include "rtc_base/numerics/sequence_number_util.h"
 #include "rtc_base/thread_annotations.h"
 
diff --git a/rtc_base/experiments/BUILD.gn b/rtc_base/experiments/BUILD.gn
index a95e258..c0e1049 100644
--- a/rtc_base/experiments/BUILD.gn
+++ b/rtc_base/experiments/BUILD.gn
@@ -63,6 +63,17 @@
   ]
 }
 
+rtc_static_library("rtt_mult_experiment") {
+  sources = [
+    "rtt_mult_experiment.cc",
+    "rtt_mult_experiment.h",
+  ]
+  deps = [
+    "../:rtc_base_approved",
+    "../../system_wrappers:field_trial_api",
+  ]
+}
+
 if (rtc_include_tests) {
   rtc_source_set("experiments_unittests") {
     testonly = true
@@ -72,11 +83,13 @@
       "field_trial_parser_unittest.cc",
       "field_trial_units_unittest.cc",
       "quality_scaling_experiment_unittest.cc",
+      "rtt_mult_experiment_unittest.cc",
     ]
     deps = [
       ":congestion_controller_experiment",
       ":field_trial_parser",
       ":quality_scaling_experiment",
+      ":rtt_mult_experiment",
       "../:rtc_base_tests_main",
       "../:rtc_base_tests_utils",
       "../../system_wrappers:field_trial_api",
diff --git a/rtc_base/experiments/rtt_mult_experiment.cc b/rtc_base/experiments/rtt_mult_experiment.cc
new file mode 100644
index 0000000..f8f7f2a
--- /dev/null
+++ b/rtc_base/experiments/rtt_mult_experiment.cc
@@ -0,0 +1,49 @@
+/*
+ *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#include "rtc_base/experiments/rtt_mult_experiment.h"
+
+#include <algorithm>
+#include <string>
+
+#include "rtc_base/logging.h"
+#include "system_wrappers/include/field_trial.h"
+
+namespace webrtc {
+
+namespace {
+const char kRttMultExperiment[] = "WebRTC-RttMult";
+const float max_rtt_mult_setting = 1.0;
+const float min_rtt_mult_setting = 0.0;
+}  // namespace
+
+bool RttMultExperiment::RttMultEnabled() {
+  return field_trial::IsEnabled(kRttMultExperiment);
+}
+
+float RttMultExperiment::GetRttMultValue() {
+  const std::string group =
+      webrtc::field_trial::FindFullName(kRttMultExperiment);
+  if (group.empty()) {
+    RTC_LOG(LS_WARNING) << "Could not find rtt_mult_experiment.";
+    return 0.0;
+  }
+
+  float rtt_mult_setting;
+  if (sscanf(group.c_str(), "Enabled-%f", &rtt_mult_setting) != 1) {
+    RTC_LOG(LS_WARNING) << "Invalid number of parameters provided.";
+    return 0.0;
+  }
+  // Bounds check rtt_mult_setting value.
+  rtt_mult_setting = std::min(rtt_mult_setting, max_rtt_mult_setting);
+  rtt_mult_setting = std::max(rtt_mult_setting, min_rtt_mult_setting);
+  return rtt_mult_setting;
+}
+
+}  // namespace webrtc
diff --git a/rtc_base/experiments/rtt_mult_experiment.h b/rtc_base/experiments/rtt_mult_experiment.h
new file mode 100644
index 0000000..d431af6
--- /dev/null
+++ b/rtc_base/experiments/rtt_mult_experiment.h
@@ -0,0 +1,26 @@
+/*
+ *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef RTC_BASE_EXPERIMENTS_RTT_MULT_EXPERIMENT_H_
+#define RTC_BASE_EXPERIMENTS_RTT_MULT_EXPERIMENT_H_
+
+namespace webrtc {
+
+class RttMultExperiment {
+ public:
+  // Returns true if the experiment is enabled.
+  static bool RttMultEnabled();
+
+  // Returns rtt_mult value from field trial.
+  static float GetRttMultValue();
+};
+
+}  // namespace webrtc
+
+#endif  // RTC_BASE_EXPERIMENTS_RTT_MULT_EXPERIMENT_H_
diff --git a/rtc_base/experiments/rtt_mult_experiment_unittest.cc b/rtc_base/experiments/rtt_mult_experiment_unittest.cc
new file mode 100644
index 0000000..0cd86d1
--- /dev/null
+++ b/rtc_base/experiments/rtt_mult_experiment_unittest.cc
@@ -0,0 +1,51 @@
+/*
+ *  Copyright 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/experiments/rtt_mult_experiment.h"
+#include "rtc_base/gunit.h"
+#include "test/field_trial.h"
+
+namespace webrtc {
+
+TEST(RttMultExperimentTest, RttMultDisabledByDefault) {
+  EXPECT_FALSE(RttMultExperiment::RttMultEnabled());
+}
+
+TEST(RttMultExperimentTest, RttMultEnabledByFieldTrial) {
+  webrtc::test::ScopedFieldTrials field_trials("WebRTC-RttMult/Enabled-0.25/");
+  EXPECT_TRUE(RttMultExperiment::RttMultEnabled());
+}
+
+TEST(RttMultExperimentTest, RttMultTestValue) {
+  webrtc::test::ScopedFieldTrials field_trials("WebRTC-RttMult/Enabled-0.25/");
+  EXPECT_EQ(0.25, RttMultExperiment::GetRttMultValue());
+}
+
+TEST(RttMultExperimentTest, RttMultTestMalformedEnabled) {
+  webrtc::test::ScopedFieldTrials field_trials("WebRTC-RttMult/Enable-0.25/");
+  EXPECT_FALSE(RttMultExperiment::RttMultEnabled());
+}
+
+TEST(RttMultExperimentTest, RttMultTestValueOutOfBoundsPositive) {
+  webrtc::test::ScopedFieldTrials field_trials("WebRTC-RttMult/Enabled-1.5/");
+  EXPECT_EQ(1.0, RttMultExperiment::GetRttMultValue());
+}
+
+TEST(RttMultExperimentTest, RttMultTestValueOutOfBoundsNegative) {
+  webrtc::test::ScopedFieldTrials field_trials("WebRTC-RttMult/Enabled--0.5/");
+  EXPECT_EQ(0.0, RttMultExperiment::GetRttMultValue());
+}
+
+TEST(RttMultExperimentTest, RttMultTestMalformedValue) {
+  webrtc::test::ScopedFieldTrials field_trials("WebRTC-RttMult/Enabled-0.2a5/");
+  EXPECT_NE(0.25, RttMultExperiment::GetRttMultValue());
+}
+
+}  // namespace webrtc