Move quality scaler into adaptation module

This allows for further refactoring, eventually moving
all of quality scaler out of video stream encoder.

Bug: webrtc:11222
Change-Id: Id121608da56f57549a616ccc5f141bb598668b40
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/167728
Commit-Queue: Evan Shrubsole <eshr@google.com>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30417}
diff --git a/video/overuse_frame_detector_resource_adaptation_module.cc b/video/overuse_frame_detector_resource_adaptation_module.cc
index 05813eb..e73f7fa 100644
--- a/video/overuse_frame_detector_resource_adaptation_module.cc
+++ b/video/overuse_frame_detector_resource_adaptation_module.cc
@@ -359,7 +359,7 @@
       last_input_frame_size_(absl::nullopt),
       target_frame_rate_(absl::nullopt),
       target_bitrate_bps_(absl::nullopt),
-      is_quality_scaler_enabled_(false),
+      quality_scaler_(nullptr),
       encoder_settings_(absl::nullopt),
       encoder_stats_observer_(encoder_stats_observer) {
   RTC_DCHECK(adaptation_listener_);
@@ -480,9 +480,14 @@
                                encode_duration_us);
 }
 
-void OveruseFrameDetectorResourceAdaptationModule::SetIsQualityScalerEnabled(
-    bool is_quality_scaler_enabled) {
-  is_quality_scaler_enabled_ = is_quality_scaler_enabled;
+void OveruseFrameDetectorResourceAdaptationModule::UpdateQualityScalerSettings(
+    absl::optional<VideoEncoder::QpThresholds> qp_thresholds) {
+  if (qp_thresholds.has_value()) {
+    quality_scaler_ =
+        std::make_unique<QualityScaler>(this, qp_thresholds.value());
+  } else {
+    quality_scaler_ = nullptr;
+  }
 }
 
 void OveruseFrameDetectorResourceAdaptationModule::AdaptUp(AdaptReason reason) {
@@ -824,11 +829,11 @@
       break;
     case kQuality:
       if (!IsFramerateScalingEnabled(degradation_preference_) ||
-          !is_quality_scaler_enabled_) {
+          !quality_scaler_) {
         counts.num_framerate_reductions = absl::nullopt;
       }
       if (!IsResolutionScalingEnabled(degradation_preference_) ||
-          !is_quality_scaler_enabled_) {
+          !quality_scaler_) {
         counts.num_resolution_reductions = absl::nullopt;
       }
       break;
diff --git a/video/overuse_frame_detector_resource_adaptation_module.h b/video/overuse_frame_detector_resource_adaptation_module.h
index 7d266fa..2bb05f9 100644
--- a/video/overuse_frame_detector_resource_adaptation_module.h
+++ b/video/overuse_frame_detector_resource_adaptation_module.h
@@ -63,6 +63,7 @@
   DegradationPreference degradation_preference() const {
     return degradation_preference_;
   }
+  QualityScaler* quality_scaler() const { return quality_scaler_.get(); }
 
   // ResourceAdaptationModuleInterface implementation.
   void StartResourceAdaptation(
@@ -85,12 +86,9 @@
                          int64_t capture_time_us,
                          absl::optional<int> encode_duration_us) override;
 
-  // Inform the detector whether or not the quality scaler is enabled. This
-  // helps GetActiveCounts() return absl::nullopt when appropriate.
-  // TODO(hbos): This feels really hacky, can we report the right values without
-  // this boolean? It would be really easy to report the wrong thing if this
-  // method is called incorrectly.
-  void SetIsQualityScalerEnabled(bool is_quality_scaler_enabled);
+  // Use nullopt to disable quality scaling.
+  void UpdateQualityScalerSettings(
+      absl::optional<VideoEncoder::QpThresholds> qp_thresholds);
 
   class AdaptCounter final {
    public:
@@ -209,7 +207,7 @@
   absl::optional<int> last_input_frame_size_;
   absl::optional<double> target_frame_rate_;
   absl::optional<uint32_t> target_bitrate_bps_;
-  bool is_quality_scaler_enabled_;
+  std::unique_ptr<QualityScaler> quality_scaler_;
   absl::optional<EncoderSettings> encoder_settings_;
   VideoStreamEncoderObserver* const encoder_stats_observer_;
 };
diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc
index 6eaf8c7..7ec659d 100644
--- a/video/video_stream_encoder.cc
+++ b/video/video_stream_encoder.cc
@@ -18,6 +18,7 @@
 #include <utility>
 
 #include "absl/algorithm/container.h"
+#include "absl/types/optional.h"
 #include "api/video/encoded_image.h"
 #include "api/video/i420_buffer.h"
 #include "api/video/video_bitrate_allocator_factory.h"
@@ -341,8 +342,7 @@
     rate_allocator_ = nullptr;
     bitrate_observer_ = nullptr;
     ReleaseEncoder();
-    quality_scaler_ = nullptr;
-    resource_adaptation_module_->SetIsQualityScalerEnabled(false);
+    resource_adaptation_module_->UpdateQualityScalerSettings(absl::nullopt);
     shutdown_event_.Set();
   });
 
@@ -786,7 +786,7 @@
       scaling_settings.thresholds;
 
   if (quality_scaling_allowed) {
-    if (quality_scaler_ == nullptr) {
+    if (resource_adaptation_module_->quality_scaler() == nullptr) {
       // Quality scaler has not already been configured.
 
       // Use experimental thresholds if available.
@@ -795,28 +795,24 @@
         experimental_thresholds = QualityScalingExperiment::GetQpThresholds(
             encoder_config_.codec_type);
       }
-      // Since the interface is non-public, std::make_unique can't do this
-      // upcast.
-      AdaptationObserverInterface* observer = resource_adaptation_module_.get();
-      quality_scaler_ = std::make_unique<QualityScaler>(
-          observer, experimental_thresholds ? *experimental_thresholds
-                                            : *(scaling_settings.thresholds));
-      resource_adaptation_module_->SetIsQualityScalerEnabled(true);
+      resource_adaptation_module_->UpdateQualityScalerSettings(
+          experimental_thresholds ? *experimental_thresholds
+                                  : *(scaling_settings.thresholds));
       initial_framedrop_ = 0;
     }
   } else {
-    quality_scaler_.reset(nullptr);
-    resource_adaptation_module_->SetIsQualityScalerEnabled(false);
+    resource_adaptation_module_->UpdateQualityScalerSettings(absl::nullopt);
     initial_framedrop_ = kMaxInitialFramedrop;
   }
 
+  QualityScaler* quality_scaler = resource_adaptation_module_->quality_scaler();
   if (resource_adaptation_module_->degradation_preference() ==
           DegradationPreference::BALANCED &&
-      quality_scaler_ && last_frame_info_) {
+      quality_scaler && last_frame_info_) {
     absl::optional<VideoEncoder::QpThresholds> thresholds =
         resource_adaptation_module_->GetQpThresholds();
     if (thresholds) {
-      quality_scaler_->SetQpThresholds(*thresholds);
+      quality_scaler->SetQpThresholds(*thresholds);
     }
   }
 
@@ -1553,8 +1549,10 @@
           VideoStreamEncoderObserver::DropReason::kMediaOptimization);
       encoder_queue_.PostTask([this] {
         RTC_DCHECK_RUN_ON(&encoder_queue_);
-        if (quality_scaler_)
-          quality_scaler_->ReportDroppedFrameByMediaOpt();
+        QualityScaler* quality_scaler =
+            resource_adaptation_module_->quality_scaler();
+        if (quality_scaler)
+          quality_scaler->ReportDroppedFrameByMediaOpt();
       });
       break;
     case DropReason::kDroppedByEncoder:
@@ -1562,8 +1560,10 @@
           VideoStreamEncoderObserver::DropReason::kEncoder);
       encoder_queue_.PostTask([this] {
         RTC_DCHECK_RUN_ON(&encoder_queue_);
-        if (quality_scaler_)
-          quality_scaler_->ReportDroppedFrameByEncoder();
+        QualityScaler* quality_scaler =
+            resource_adaptation_module_->quality_scaler();
+        if (quality_scaler)
+          quality_scaler->ReportDroppedFrameByEncoder();
       });
       break;
   }
@@ -1607,7 +1607,8 @@
                       << " rtt " << round_trip_time_ms;
 
   if (set_start_bitrate_bps_ > 0 && !has_seen_first_bwe_drop_ &&
-      quality_scaler_ && quality_scaler_settings_.InitialBitrateIntervalMs() &&
+      resource_adaptation_module_->quality_scaler() &&
+      quality_scaler_settings_.InitialBitrateIntervalMs() &&
       quality_scaler_settings_.InitialBitrateFactor()) {
     int64_t diff_ms = clock_->TimeInMilliseconds() - set_start_bitrate_time_ms_;
     if (diff_ms < quality_scaler_settings_.InitialBitrateIntervalMs().value() &&
@@ -1680,7 +1681,8 @@
 }
 
 bool VideoStreamEncoder::TryQualityRampup(int64_t now_ms) {
-  if (!quality_scaler_)
+  QualityScaler* quality_scaler = resource_adaptation_module_->quality_scaler();
+  if (!quality_scaler)
     return false;
 
   uint32_t bw_kbps = last_encoder_rate_settings_
@@ -1692,7 +1694,7 @@
     // Verify that encoder is at max bitrate and the QP is low.
     if (encoder_target_bitrate_bps_.value_or(0) ==
             send_codec_.maxBitrate * 1000 &&
-        quality_scaler_->QpFastFilterLow()) {
+        quality_scaler->QpFastFilterLow()) {
       return true;
     }
   }
@@ -1764,8 +1766,9 @@
       encoded_image.Timestamp(), time_sent_us,
       encoded_image.capture_time_ms_ * rtc::kNumMicrosecsPerMillisec,
       encode_duration_us);
-  if (quality_scaler_ && encoded_image.qp_ >= 0)
-    quality_scaler_->ReportQp(encoded_image.qp_, time_sent_us);
+  QualityScaler* quality_scaler = resource_adaptation_module_->quality_scaler();
+  if (quality_scaler && encoded_image.qp_ >= 0)
+    quality_scaler->ReportQp(encoded_image.qp_, time_sent_us);
   if (bitrate_adjuster_) {
     bitrate_adjuster_->OnEncodedFrame(encoded_image, temporal_index);
   }
diff --git a/video/video_stream_encoder.h b/video/video_stream_encoder.h
index 01d7738..97a4a66 100644
--- a/video/video_stream_encoder.h
+++ b/video/video_stream_encoder.h
@@ -226,9 +226,6 @@
   const RateControlSettings rate_control_settings_;
   const QualityScalerSettings quality_scaler_settings_;
 
-  std::unique_ptr<QualityScaler> quality_scaler_ RTC_GUARDED_BY(&encoder_queue_)
-      RTC_PT_GUARDED_BY(&encoder_queue_);
-
   VideoStreamEncoderObserver* const encoder_stats_observer_;
   // |thread_checker_| checks that public methods that are related to lifetime
   // of VideoStreamEncoder are called on the same thread.