Add settings to turn off VP8 base layer qp limit

This quality boost means that we sometimes drop a _lot_ of frames in the
base layer. It also interacts poorly with the bitrate adjuster since
even if frames are dropped they are often over-sized.

The setting still leaves the current behavior as default, but can be
changed using the WebRTC-VideoRateControl field trial.

Bug: webrtc:10155
Change-Id: I1a92ec69bab61b5148fe9d8bc391ac5ee1019367
Reviewed-on: https://webrtc-review.googlesource.com/c/122840
Commit-Queue: Erik Språng <sprang@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26659}
diff --git a/media/BUILD.gn b/media/BUILD.gn
index c016def..b3195a1 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -180,6 +180,7 @@
     "../rtc_base:checks",
     "../rtc_base:rtc_base_approved",
     "../rtc_base:sequenced_task_checker",
+    "../rtc_base/experiments:rate_control_settings",
     "../system_wrappers",
     "../system_wrappers:field_trial",
     "//third_party/abseil-cpp/absl/types:optional",
diff --git a/media/engine/simulcast_encoder_adapter.cc b/media/engine/simulcast_encoder_adapter.cc
index f6d0f24..3d184bd 100644
--- a/media/engine/simulcast_encoder_adapter.cc
+++ b/media/engine/simulcast_encoder_adapter.cc
@@ -27,6 +27,7 @@
 #include "modules/video_coding/utility/simulcast_rate_allocator.h"
 #include "rtc_base/atomic_ops.h"
 #include "rtc_base/checks.h"
+#include "rtc_base/experiments/rate_control_settings.h"
 #include "system_wrappers/include/field_trial.h"
 #include "third_party/libyuv/include/libyuv/scale.h"
 
@@ -124,7 +125,9 @@
       factory_(factory),
       video_format_(format),
       encoded_complete_callback_(nullptr),
-      experimental_boosted_screenshare_qp_(GetScreenshareBoostedQpValue()) {
+      experimental_boosted_screenshare_qp_(GetScreenshareBoostedQpValue()),
+      boost_base_layer_quality_(RateControlSettings::ParseFromFieldTrials()
+                                    .Vp8BoostBaseLayerQuality()) {
   RTC_DCHECK(factory_);
   encoder_info_.implementation_name = "SimulcastEncoderAdapter";
 
@@ -534,7 +537,7 @@
       if (experimental_boosted_screenshare_qp_) {
         stream_codec->qpMax = *experimental_boosted_screenshare_qp_;
       }
-    } else {
+    } else if (boost_base_layer_quality_) {
       stream_codec->qpMax = kLowestResMaxQp;
     }
   }
diff --git a/media/engine/simulcast_encoder_adapter.h b/media/engine/simulcast_encoder_adapter.h
index b7b6c7f2..7029bc1 100644
--- a/media/engine/simulcast_encoder_adapter.h
+++ b/media/engine/simulcast_encoder_adapter.h
@@ -116,6 +116,7 @@
   std::stack<std::unique_ptr<VideoEncoder>> stored_encoders_;
 
   const absl::optional<unsigned int> experimental_boosted_screenshare_qp_;
+  const bool boost_base_layer_quality_;
 };
 
 }  // namespace webrtc
diff --git a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
index 9dc91f9..7a23325 100644
--- a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
+++ b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
@@ -32,7 +32,6 @@
 #include "modules/video_coding/utility/simulcast_utility.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/experiments/field_trial_parser.h"
-#include "rtc_base/experiments/rate_control_settings.h"
 #include "rtc_base/trace_event.h"
 #include "system_wrappers/include/field_trial.h"
 #include "third_party/libyuv/include/libyuv/scale.h"
@@ -166,8 +165,7 @@
 LibvpxVp8Encoder::LibvpxVp8Encoder(std::unique_ptr<LibvpxInterface> interface)
     : libvpx_(std::move(interface)),
       experimental_cpu_speed_config_arm_(CpuSpeedExperiment::GetConfigs()),
-      trusted_rate_controller_(RateControlSettings::ParseFromFieldTrials()
-                                   .LibvpxVp8TrustedRateController()),
+      rate_control_settings_(RateControlSettings::ParseFromFieldTrials()),
       encoded_complete_callback_(nullptr),
       inited_(false),
       timestamp_(0),
@@ -250,7 +248,8 @@
     // possibly more dropped frames, so we only do this if the frame rate is
     // above some threshold (base temporal layer is down to 1/4 for 3 layers).
     // We may want to condition this on bitrate later.
-    if (new_framerate > 20) {
+    if (rate_control_settings_.Vp8BoostBaseLayerQuality() &&
+        new_framerate > 20) {
       configurations_[encoders_.size() - 1].rc_max_quantizer = 45;
     } else {
       // Go back to default value set in InitEncode.
@@ -943,7 +942,8 @@
   EncoderInfo info;
   info.supports_native_handle = false;
   info.implementation_name = "libvpx";
-  info.has_trusted_rate_controller = trusted_rate_controller_;
+  info.has_trusted_rate_controller =
+      rate_control_settings_.LibvpxVp8TrustedRateController();
   info.is_hardware_accelerated = false;
   info.has_internal_source = false;
 
diff --git a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h
index 4be5809..c8c7b08 100644
--- a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h
+++ b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h
@@ -24,6 +24,7 @@
 #include "modules/video_coding/codecs/vp8/libvpx_interface.h"
 #include "modules/video_coding/include/video_codec_interface.h"
 #include "rtc_base/experiments/cpu_speed_experiment.h"
+#include "rtc_base/experiments/rate_control_settings.h"
 
 #include "vpx/vp8cx.h"
 #include "vpx/vpx_encoder.h"
@@ -86,7 +87,7 @@
 
   const absl::optional<std::vector<CpuSpeedExperiment::Config>>
       experimental_cpu_speed_config_arm_;
-  const bool trusted_rate_controller_;
+  const RateControlSettings rate_control_settings_;
 
   EncodedImageCallback* encoded_complete_callback_;
   VideoCodec codec_;
diff --git a/rtc_base/experiments/rate_control_settings.cc b/rtc_base/experiments/rate_control_settings.cc
index 0f19b78..4e2d745 100644
--- a/rtc_base/experiments/rate_control_settings.cc
+++ b/rtc_base/experiments/rate_control_settings.cc
@@ -122,12 +122,13 @@
                                 kScreenshareHysteresisFieldTrialname,
                                 kDefaultScreenshareHysteresisFactor)),
       probe_max_allocation_("probe_max_allocation", true),
-      bitrate_adjuster_("bitrate_adjuster", false) {
-  ParseFieldTrial(
-      {&congestion_window_, &congestion_window_pushback_, &pacing_factor_,
-       &alr_probing_, &trust_vp8_, &trust_vp9_, &video_hysteresis_,
-       &screenshare_hysteresis_, &probe_max_allocation_, &bitrate_adjuster_},
-      key_value_config->Lookup("WebRTC-VideoRateControl"));
+      bitrate_adjuster_("bitrate_adjuster", false),
+      vp8_s0_boost_("vp8_s0_boost", true) {
+  ParseFieldTrial({&congestion_window_, &congestion_window_pushback_,
+                   &pacing_factor_, &alr_probing_, &trust_vp8_, &trust_vp9_,
+                   &video_hysteresis_, &screenshare_hysteresis_,
+                   &probe_max_allocation_, &bitrate_adjuster_, &vp8_s0_boost_},
+                  key_value_config->Lookup("WebRTC-VideoRateControl"));
 }
 
 RateControlSettings::~RateControlSettings() = default;
@@ -175,6 +176,10 @@
   return trust_vp8_.Get();
 }
 
+bool RateControlSettings::Vp8BoostBaseLayerQuality() const {
+  return vp8_s0_boost_.Get();
+}
+
 bool RateControlSettings::LibvpxVp9TrustedRateController() const {
   return trust_vp9_.Get();
 }
diff --git a/rtc_base/experiments/rate_control_settings.h b/rtc_base/experiments/rate_control_settings.h
index e40c7aa..0898f9b 100644
--- a/rtc_base/experiments/rate_control_settings.h
+++ b/rtc_base/experiments/rate_control_settings.h
@@ -41,6 +41,7 @@
   bool UseAlrProbing() const;
 
   bool LibvpxVp8TrustedRateController() const;
+  bool Vp8BoostBaseLayerQuality() const;
   bool LibvpxVp9TrustedRateController() const;
 
   // TODO(bugs.webrtc.org/10272): Remove one of these when we have merged
@@ -69,6 +70,7 @@
   FieldTrialParameter<double> screenshare_hysteresis_;
   FieldTrialParameter<bool> probe_max_allocation_;
   FieldTrialParameter<bool> bitrate_adjuster_;
+  FieldTrialParameter<bool> vp8_s0_boost_;
 };
 
 }  // namespace webrtc