Remove VideoStreamEncoderObserver::AdaptationReason::kNone

Replaces this with 2 methods instead, adding clarity.

ClearAdaptationStats
- Resets the adaptations statistics to 0. This is done,
when the degredation is reset, for example when the preference
is changed to/from BALANCED.

UpdateAdaptationMaskingSettings
- Updates the settings for adaptation statistics reporting.
This way we don't report quality adaptations if quality scaling
is not enabled (same for resolution/fps scaling).

The adaptation counting inside the SendStatisticsProxy is
now done in a struct that counts the totals, and then masks
out these counts based on the adaptation settings. The
MaskedAdaptationSteps uses optionals to hide the values we
shoudn't report, while the AdaptationSteps always hold the real
totals.

All tests have been updated to use the Reset/Clear method as needed.

Now that AdaptationCounters and AdaptSteps use the same structure,
AdaptationCounters was moved to api/video and replaces AdaptSteps.

The AdaptReason enum is also redundant now, and will be removed
in a follow-up CL.

R=hbos@webrtc.org

Bug: webrtc:11392
Change-Id: Iaed6488581325d341a056b5bbf76a01c19d6c282
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/171685
Reviewed-by: Niels Moller <nisse@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Commit-Queue: Evan Shrubsole <eshr@google.com>
Cr-Commit-Position: refs/heads/master@{#31083}
diff --git a/api/video/BUILD.gn b/api/video/BUILD.gn
index 401cee7..eb9e919 100644
--- a/api/video/BUILD.gn
+++ b/api/video/BUILD.gn
@@ -243,12 +243,12 @@
   visibility = [ "*" ]
   sources = [
     "video_stream_encoder_interface.h",
-    "video_stream_encoder_observer.cc",
     "video_stream_encoder_observer.h",
     "video_stream_encoder_settings.h",
   ]
 
   deps = [
+    ":video_adaptation",
     ":video_bitrate_allocation",
     ":video_bitrate_allocator",
     ":video_bitrate_allocator_factory",
diff --git a/api/video/video_stream_encoder_observer.cc b/api/video/video_stream_encoder_observer.cc
deleted file mode 100644
index 3b9bd52..0000000
--- a/api/video/video_stream_encoder_observer.cc
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- *  Copyright (c) 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 "api/video/video_stream_encoder_observer.h"
-
-namespace webrtc {
-
-VideoStreamEncoderObserver::AdaptationSteps::AdaptationSteps() = default;
-
-}  // namespace webrtc
diff --git a/api/video/video_stream_encoder_observer.h b/api/video/video_stream_encoder_observer.h
index 9fd462c..ab889bc 100644
--- a/api/video/video_stream_encoder_observer.h
+++ b/api/video/video_stream_encoder_observer.h
@@ -15,6 +15,7 @@
 #include <vector>
 
 #include "absl/types/optional.h"
+#include "api/video/video_adaptation_counters.h"
 #include "api/video/video_bitrate_allocation.h"
 #include "api/video/video_codec_constants.h"
 #include "api/video_codecs/video_encoder.h"
@@ -38,22 +39,27 @@
 
 class VideoStreamEncoderObserver : public CpuOveruseMetricsObserver {
  public:
-  // Number of resolution and framerate reductions (unset if disabled).
-  struct AdaptationSteps {
-    AdaptationSteps();
-    absl::optional<int> num_resolution_reductions = 0;
-    absl::optional<int> num_framerate_reductions = 0;
-  };
-
   // TODO(nisse): There are too many enums to represent this. Besides
   // this one, see AdaptationObserverInterface::AdaptReason and
   // WebRtcVideoChannel::AdaptReason.
   enum class AdaptationReason {
-    kNone,  // Used for reset of counters.
     kCpu,
     kQuality,
   };
 
+  struct AdaptationSettings {
+    AdaptationSettings()
+        : resolution_scaling_enabled(false), framerate_scaling_enabled(false) {}
+
+    AdaptationSettings(bool resolution_scaling_enabled,
+                       bool framerate_scaling_enabled)
+        : resolution_scaling_enabled(resolution_scaling_enabled),
+          framerate_scaling_enabled(framerate_scaling_enabled) {}
+
+    bool resolution_scaling_enabled;
+    bool framerate_scaling_enabled;
+  };
+
   // TODO(nisse): Duplicates enum EncodedImageCallback::DropReason.
   enum class DropReason {
     kSource,
@@ -83,9 +89,15 @@
       const VideoEncoderConfig& encoder_config,
       const std::vector<VideoStream>& streams) = 0;
 
-  virtual void OnAdaptationChanged(AdaptationReason reason,
-                                   const AdaptationSteps& cpu_steps,
-                                   const AdaptationSteps& quality_steps) = 0;
+  virtual void OnAdaptationChanged(
+      AdaptationReason reason,
+      const VideoAdaptationCounters& cpu_steps,
+      const VideoAdaptationCounters& quality_steps) = 0;
+  virtual void ClearAdaptationStats() = 0;
+
+  virtual void UpdateAdaptationSettings(
+      AdaptationSettings cpu_settings,
+      AdaptationSettings quality_settings) = 0;
   virtual void OnMinPixelLimitReached() = 0;
   virtual void OnInitialQualityResolutionAdaptDown() = 0;
 
diff --git a/video/adaptation/resource_adaptation_processor.cc b/video/adaptation/resource_adaptation_processor.cc
index bcc4e1d..26d1adc 100644
--- a/video/adaptation/resource_adaptation_processor.cc
+++ b/video/adaptation/resource_adaptation_processor.cc
@@ -93,6 +93,16 @@
   return counters;
 }
 
+VideoStreamEncoderObserver::AdaptationReason ToAdaptationReason(
+    AdaptationObserverInterface::AdaptReason reason) {
+  switch (reason) {
+    case AdaptationObserverInterface::kQuality:
+      return VideoStreamEncoderObserver::AdaptationReason::kQuality;
+    case AdaptationObserverInterface::kCpu:
+      return VideoStreamEncoderObserver::AdaptationReason::kCpu;
+  }
+}
+
 }  // namespace
 
 class ResourceAdaptationProcessor::InitialFrameDropper {
@@ -253,10 +263,13 @@
 void ResourceAdaptationProcessor::SetDegradationPreference(
     DegradationPreference degradation_preference) {
   degradation_preference_ = degradation_preference;
+  UpdateStatsAdaptationSettings();
+
   if (stream_adapter_->SetDegradationPreference(degradation_preference) ==
       VideoStreamAdapter::SetDegradationPreferenceResult::
           kRestrictionsCleared) {
     active_counts_.fill(VideoAdaptationCounters());
+    encoder_stats_observer_->ClearAdaptationStats();
   }
   MaybeUpdateVideoSourceRestrictions();
 }
@@ -293,6 +306,7 @@
 void ResourceAdaptationProcessor::ResetVideoSourceRestrictions() {
   stream_adapter_->ClearRestrictions();
   active_counts_.fill(VideoAdaptationCounters());
+  encoder_stats_observer_->ClearAdaptationStats();
   MaybeUpdateVideoSourceRestrictions();
 }
 
@@ -401,11 +415,7 @@
       quality_scaler_resource_->SetQpThresholds(*thresholds);
     }
   }
-
-  encoder_stats_observer_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone,
-      GetActiveCounts(AdaptationObserverInterface::AdaptReason::kCpu),
-      GetActiveCounts(AdaptationObserverInterface::AdaptReason::kQuality));
+  UpdateStatsAdaptationSettings();
 }
 
 ResourceListenerResponse
@@ -644,52 +654,24 @@
 
   OnAdaptationCountChanged(total_counts, &active_count, &other_active);
 
-  switch (reason) {
-    case AdaptationObserverInterface::AdaptReason::kCpu:
-      encoder_stats_observer_->OnAdaptationChanged(
-          VideoStreamEncoderObserver::AdaptationReason::kCpu,
-          GetActiveCounts(AdaptationObserverInterface::AdaptReason::kCpu),
-          GetActiveCounts(AdaptationObserverInterface::AdaptReason::kQuality));
-      break;
-    case AdaptationObserverInterface::AdaptReason::kQuality:
-      encoder_stats_observer_->OnAdaptationChanged(
-          VideoStreamEncoderObserver::AdaptationReason::kQuality,
-          GetActiveCounts(AdaptationObserverInterface::AdaptReason::kCpu),
-          GetActiveCounts(AdaptationObserverInterface::AdaptReason::kQuality));
-      break;
-  }
+  encoder_stats_observer_->OnAdaptationChanged(
+      ToAdaptationReason(reason),
+      std::get<AdaptationObserverInterface::AdaptReason::kCpu>(active_counts_),
+      std::get<AdaptationObserverInterface::AdaptReason::kQuality>(
+          active_counts_));
 }
 
-VideoStreamEncoderObserver::AdaptationSteps
-ResourceAdaptationProcessor::GetActiveCounts(
-    AdaptationObserverInterface::AdaptReason reason) {
-  // TODO(https://crbug.com/webrtc/11392) Ideally this shuold be moved out of
-  // this class and into the encoder_stats_observer_.
-  const VideoAdaptationCounters counters = active_counts_[reason];
+void ResourceAdaptationProcessor::UpdateStatsAdaptationSettings() const {
+  VideoStreamEncoderObserver::AdaptationSettings cpu_settings(
+      IsResolutionScalingEnabled(degradation_preference_),
+      IsFramerateScalingEnabled(degradation_preference_));
 
-  VideoStreamEncoderObserver::AdaptationSteps counts =
-      VideoStreamEncoderObserver::AdaptationSteps();
-  counts.num_resolution_reductions = counters.resolution_adaptations;
-  counts.num_framerate_reductions = counters.fps_adaptations;
-  switch (reason) {
-    case AdaptationObserverInterface::AdaptReason::kCpu:
-      if (!IsFramerateScalingEnabled(degradation_preference_))
-        counts.num_framerate_reductions = absl::nullopt;
-      if (!IsResolutionScalingEnabled(degradation_preference_))
-        counts.num_resolution_reductions = absl::nullopt;
-      break;
-    case AdaptationObserverInterface::AdaptReason::kQuality:
-      if (!IsFramerateScalingEnabled(degradation_preference_) ||
-          !quality_scaler_resource_->is_started()) {
-        counts.num_framerate_reductions = absl::nullopt;
-      }
-      if (!IsResolutionScalingEnabled(degradation_preference_) ||
-          !quality_scaler_resource_->is_started()) {
-        counts.num_resolution_reductions = absl::nullopt;
-      }
-      break;
-  }
-  return counts;
+  VideoStreamEncoderObserver::AdaptationSettings quality_settings =
+      quality_scaler_resource_->is_started()
+          ? cpu_settings
+          : VideoStreamEncoderObserver::AdaptationSettings();
+  encoder_stats_observer_->UpdateAdaptationSettings(cpu_settings,
+                                                    quality_settings);
 }
 
 VideoStreamAdapter::VideoInputMode
diff --git a/video/adaptation/resource_adaptation_processor.h b/video/adaptation/resource_adaptation_processor.h
index f056b1c..aaaf5fb 100644
--- a/video/adaptation/resource_adaptation_processor.h
+++ b/video/adaptation/resource_adaptation_processor.h
@@ -140,8 +140,6 @@
 
   CpuOveruseOptions GetCpuOveruseOptions() const;
   int LastInputFrameSizeOrDefault() const;
-  VideoStreamEncoderObserver::AdaptationSteps GetActiveCounts(
-      AdaptationObserverInterface::AdaptReason reason);
   VideoStreamAdapter::VideoInputMode GetVideoInputMode() const;
 
   // Makes |video_source_restrictions_| up-to-date and informs the
@@ -157,6 +155,7 @@
       absl::optional<VideoEncoder::QpThresholds> qp_thresholds);
 
   void UpdateAdaptationStats(AdaptationObserverInterface::AdaptReason reason);
+  void UpdateStatsAdaptationSettings() const;
 
   // Checks to see if we should execute the quality rampup experiment. The
   // experiment resets all video restrictions at the start of the call in the
diff --git a/video/send_statistics_proxy.cc b/video/send_statistics_proxy.cc
index f2cdbc96..b973275 100644
--- a/video/send_statistics_proxy.cc
+++ b/video/send_statistics_proxy.cc
@@ -141,8 +141,6 @@
       content_type_(content_type),
       start_ms_(clock->TimeInMilliseconds()),
       encode_time_(kEncodeTimeWeigthFactor),
-      quality_downscales_(-1),
-      cpu_downscales_(-1),
       quality_limitation_reason_tracker_(clock_),
       media_byte_rate_tracker_(kBucketSizeMs, kBucketCount),
       encoded_frame_rate_tracker_(kBucketSizeMs, kBucketCount),
@@ -719,9 +717,9 @@
     uma_container_->quality_adapt_timer_.Stop(now_ms);
   } else {
     // Start adaptation stats if scaling is enabled.
-    if (cpu_downscales_ >= 0)
+    if (adaptations_.MaskedCpuCounts().resolution_adaptations.has_value())
       uma_container_->cpu_adapt_timer_.Start(now_ms);
-    if (quality_downscales_ >= 0)
+    if (adaptations_.MaskedQualityCounts().resolution_adaptations.has_value())
       uma_container_->quality_adapt_timer_.Start(now_ms);
     // Stop pause explicitly for stats that may be zero/not updated for some
     // time.
@@ -1012,12 +1010,15 @@
     encoded_frame_rate_tracker_.AddSamples(1);
   }
 
-  stats_.bw_limited_resolution |= quality_downscales_ > 0;
+  absl::optional<int> downscales =
+      adaptations_.MaskedQualityCounts().resolution_adaptations;
+  stats_.bw_limited_resolution |=
+      (downscales.has_value() && downscales.value() > 0);
 
-  if (quality_downscales_ != -1) {
-    uma_container_->quality_limited_frame_counter_.Add(quality_downscales_ > 0);
-    if (quality_downscales_ > 0)
-      uma_container_->quality_downscales_counter_.Add(quality_downscales_);
+  if (downscales.has_value()) {
+    uma_container_->quality_limited_frame_counter_.Add(downscales.value() > 0);
+    if (downscales.value() > 0)
+      uma_container_->quality_downscales_counter_.Add(downscales.value());
   }
 }
 
@@ -1045,7 +1046,7 @@
   uma_container_->input_fps_counter_.Add(1);
   uma_container_->input_width_counter_.Add(width);
   uma_container_->input_height_counter_.Add(height);
-  if (cpu_downscales_ >= 0) {
+  if (adaptations_.MaskedCpuCounts().resolution_adaptations.has_value()) {
     uma_container_->cpu_limited_frame_counter_.Add(
         stats_.cpu_limited_resolution);
   }
@@ -1077,39 +1078,56 @@
   }
 }
 
+void SendStatisticsProxy::ClearAdaptationStats() {
+  rtc::CritScope lock(&crit_);
+  adaptations_.set_cpu_counts(VideoAdaptationCounters());
+  adaptations_.set_quality_counts(VideoAdaptationCounters());
+  UpdateAdaptationStats();
+}
+
+void SendStatisticsProxy::UpdateAdaptationSettings(
+    VideoStreamEncoderObserver::AdaptationSettings cpu_settings,
+    VideoStreamEncoderObserver::AdaptationSettings quality_settings) {
+  rtc::CritScope lock(&crit_);
+  adaptations_.UpdateMaskingSettings(cpu_settings, quality_settings);
+  SetAdaptTimer(adaptations_.MaskedCpuCounts(),
+                &uma_container_->cpu_adapt_timer_);
+  SetAdaptTimer(adaptations_.MaskedQualityCounts(),
+                &uma_container_->quality_adapt_timer_);
+  UpdateAdaptationStats();
+}
+
 void SendStatisticsProxy::OnAdaptationChanged(
     AdaptationReason reason,
-    const AdaptationSteps& cpu_counts,
-    const AdaptationSteps& quality_counts) {
+    const VideoAdaptationCounters& cpu_counters,
+    const VideoAdaptationCounters& quality_counters) {
   rtc::CritScope lock(&crit_);
+
+  MaskedAdaptationCounts receiver = adaptations_.MaskedQualityCounts();
+  adaptations_.set_cpu_counts(cpu_counters);
+  adaptations_.set_quality_counts(quality_counters);
   switch (reason) {
-    case AdaptationReason::kNone:
-      SetAdaptTimer(cpu_counts, &uma_container_->cpu_adapt_timer_);
-      SetAdaptTimer(quality_counts, &uma_container_->quality_adapt_timer_);
-      break;
     case AdaptationReason::kCpu:
       ++stats_.number_of_cpu_adapt_changes;
       break;
     case AdaptationReason::kQuality:
-      TryUpdateInitialQualityResolutionAdaptUp(quality_counts);
+      TryUpdateInitialQualityResolutionAdaptUp(
+          receiver.resolution_adaptations,
+          adaptations_.MaskedQualityCounts().resolution_adaptations);
       ++stats_.number_of_quality_adapt_changes;
       break;
   }
-
-  cpu_downscales_ = cpu_counts.num_resolution_reductions.value_or(-1);
-  quality_downscales_ = quality_counts.num_resolution_reductions.value_or(-1);
-
-  cpu_counts_ = cpu_counts;
-  quality_counts_ = quality_counts;
-
   UpdateAdaptationStats();
 }
 
 void SendStatisticsProxy::UpdateAdaptationStats() {
-  bool is_cpu_limited = cpu_counts_.num_resolution_reductions > 0 ||
-                        cpu_counts_.num_framerate_reductions > 0;
-  bool is_bandwidth_limited = quality_counts_.num_resolution_reductions > 0 ||
-                              quality_counts_.num_framerate_reductions > 0 ||
+  auto cpu_counts = adaptations_.MaskedCpuCounts();
+  auto quality_counts = adaptations_.MaskedQualityCounts();
+
+  bool is_cpu_limited = cpu_counts.resolution_adaptations > 0 ||
+                        cpu_counts.num_framerate_reductions > 0;
+  bool is_bandwidth_limited = quality_counts.resolution_adaptations > 0 ||
+                              quality_counts.num_framerate_reductions > 0 ||
                               bw_limited_layers_ || internal_encoder_scaler_;
   if (is_bandwidth_limited) {
     // We may be both CPU limited and bandwidth limited at the same time but
@@ -1126,10 +1144,10 @@
         QualityLimitationReason::kNone);
   }
 
-  stats_.cpu_limited_resolution = cpu_counts_.num_resolution_reductions > 0;
-  stats_.cpu_limited_framerate = cpu_counts_.num_framerate_reductions > 0;
-  stats_.bw_limited_resolution = quality_counts_.num_resolution_reductions > 0;
-  stats_.bw_limited_framerate = quality_counts_.num_framerate_reductions > 0;
+  stats_.cpu_limited_resolution = cpu_counts.resolution_adaptations > 0;
+  stats_.cpu_limited_framerate = cpu_counts.num_framerate_reductions > 0;
+  stats_.bw_limited_resolution = quality_counts.resolution_adaptations > 0;
+  stats_.bw_limited_framerate = quality_counts.num_framerate_reductions > 0;
   // If bitrate allocator has disabled some layers frame-rate or resolution are
   // limited depending on the encoder configuration.
   if (bw_limited_layers_) {
@@ -1211,13 +1229,15 @@
 }
 
 void SendStatisticsProxy::TryUpdateInitialQualityResolutionAdaptUp(
-    const AdaptationSteps& quality_counts) {
+    absl::optional<int> old_quality_downscales,
+    absl::optional<int> updated_quality_downscales) {
   if (uma_container_->initial_quality_changes_.down == 0)
     return;
 
-  if (quality_downscales_ > 0 &&
-      quality_counts.num_resolution_reductions.value_or(-1) <
-          quality_downscales_) {
+  if (old_quality_downscales.has_value() &&
+      old_quality_downscales.value() > 0 &&
+      updated_quality_downscales.value_or(-1) <
+          old_quality_downscales.value()) {
     // Adapting up in quality.
     if (uma_container_->initial_quality_changes_.down >
         uma_container_->initial_quality_changes_.up) {
@@ -1226,9 +1246,9 @@
   }
 }
 
-void SendStatisticsProxy::SetAdaptTimer(const AdaptationSteps& counts,
+void SendStatisticsProxy::SetAdaptTimer(const MaskedAdaptationCounts& counts,
                                         StatsTimer* timer) {
-  if (counts.num_resolution_reductions || counts.num_framerate_reductions) {
+  if (counts.resolution_adaptations || counts.num_framerate_reductions) {
     // Adaptation enabled.
     if (!stats_.suspended)
       timer->Start(clock_->TimeInMilliseconds());
@@ -1409,4 +1429,45 @@
     return -1;
   return static_cast<int>((sum * multiplier / num_samples) + 0.5f);
 }
+
+SendStatisticsProxy::MaskedAdaptationCounts
+SendStatisticsProxy::Adaptations::MaskedCpuCounts() const {
+  return Mask(cpu_counts_, cpu_settings_);
+}
+
+SendStatisticsProxy::MaskedAdaptationCounts
+SendStatisticsProxy::Adaptations::MaskedQualityCounts() const {
+  return Mask(quality_counts_, quality_settings_);
+}
+
+void SendStatisticsProxy::Adaptations::set_cpu_counts(
+    const VideoAdaptationCounters& cpu_counts) {
+  cpu_counts_ = cpu_counts;
+}
+
+void SendStatisticsProxy::Adaptations::set_quality_counts(
+    const VideoAdaptationCounters& quality_counts) {
+  quality_counts_ = quality_counts;
+}
+void SendStatisticsProxy::Adaptations::UpdateMaskingSettings(
+    VideoStreamEncoderObserver::AdaptationSettings cpu_settings,
+    VideoStreamEncoderObserver::AdaptationSettings quality_settings) {
+  cpu_settings_ = std::move(cpu_settings);
+  quality_settings_ = std::move(quality_settings);
+}
+
+SendStatisticsProxy::MaskedAdaptationCounts
+SendStatisticsProxy::Adaptations::Mask(
+    const VideoAdaptationCounters& counters,
+    const VideoStreamEncoderObserver::AdaptationSettings& settings) const {
+  MaskedAdaptationCounts masked_counts;
+  if (settings.resolution_scaling_enabled) {
+    masked_counts.resolution_adaptations = counters.resolution_adaptations;
+  }
+  if (settings.framerate_scaling_enabled) {
+    masked_counts.num_framerate_reductions = counters.fps_adaptations;
+  }
+  return masked_counts;
+}
+
 }  // namespace webrtc
diff --git a/video/send_statistics_proxy.h b/video/send_statistics_proxy.h
index abe3999..1bd79d8 100644
--- a/video/send_statistics_proxy.h
+++ b/video/send_statistics_proxy.h
@@ -70,9 +70,13 @@
   void OnFrameDropped(DropReason) override;
 
   // Adaptation stats.
-  void OnAdaptationChanged(AdaptationReason reason,
-                           const AdaptationSteps& cpu_counts,
-                           const AdaptationSteps& quality_counts) override;
+  void OnAdaptationChanged(
+      AdaptationReason reason,
+      const VideoAdaptationCounters& cpu_counters,
+      const VideoAdaptationCounters& quality_counters) override;
+  void ClearAdaptationStats() override;
+  void UpdateAdaptationSettings(AdaptationSettings cpu_settings,
+                                AdaptationSettings quality_settings) override;
 
   void OnBitrateAllocationUpdated(
       const VideoCodec& codec,
@@ -223,11 +227,38 @@
   VideoSendStream::StreamStats* GetStatsEntry(uint32_t ssrc)
       RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
 
-  void SetAdaptTimer(const AdaptationSteps& counts, StatsTimer* timer)
+  struct MaskedAdaptationCounts {
+    absl::optional<int> resolution_adaptations = absl::nullopt;
+    absl::optional<int> num_framerate_reductions = absl::nullopt;
+  };
+
+  struct Adaptations {
+   public:
+    MaskedAdaptationCounts MaskedCpuCounts() const;
+    MaskedAdaptationCounts MaskedQualityCounts() const;
+
+    void set_cpu_counts(const VideoAdaptationCounters& cpu_counts);
+    void set_quality_counts(const VideoAdaptationCounters& quality_counts);
+
+    void UpdateMaskingSettings(AdaptationSettings cpu_settings,
+                               AdaptationSettings quality_settings);
+
+   private:
+    VideoAdaptationCounters cpu_counts_;
+    AdaptationSettings cpu_settings_;
+    VideoAdaptationCounters quality_counts_;
+    AdaptationSettings quality_settings_;
+
+    MaskedAdaptationCounts Mask(const VideoAdaptationCounters& counters,
+                                const AdaptationSettings& settings) const;
+  };
+
+  void SetAdaptTimer(const MaskedAdaptationCounts& counts, StatsTimer* timer)
       RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
   void UpdateAdaptationStats() RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
   void TryUpdateInitialQualityResolutionAdaptUp(
-      const AdaptationSteps& quality_counts)
+      absl::optional<int> old_quality_downscales,
+      absl::optional<int> updated_quality_downscales)
       RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
 
   void UpdateEncoderFallbackStats(const CodecSpecificInfo* codec_info,
@@ -250,8 +281,6 @@
   VideoSendStream::Stats stats_ RTC_GUARDED_BY(crit_);
   std::map<uint32_t, StatsUpdateTimes> update_times_ RTC_GUARDED_BY(crit_);
   rtc::ExpFilter encode_time_ RTC_GUARDED_BY(crit_);
-  int quality_downscales_ RTC_GUARDED_BY(crit_);
-  int cpu_downscales_ RTC_GUARDED_BY(crit_);
   QualityLimitationReasonTracker quality_limitation_reason_tracker_
       RTC_GUARDED_BY(crit_);
   rtc::RateTracker media_byte_rate_tracker_ RTC_GUARDED_BY(crit_);
@@ -268,8 +297,7 @@
   bool bw_limited_layers_ RTC_GUARDED_BY(crit_);
   // Indicastes if the encoder internally downscales input image.
   bool internal_encoder_scaler_ RTC_GUARDED_BY(crit_);
-  AdaptationSteps cpu_counts_ RTC_GUARDED_BY(crit_);
-  AdaptationSteps quality_counts_ RTC_GUARDED_BY(crit_);
+  Adaptations adaptations_ RTC_GUARDED_BY(crit_);
 
   struct EncoderChangeEvent {
     std::string previous_encoder_implementation;
diff --git a/video/send_statistics_proxy_unittest.cc b/video/send_statistics_proxy_unittest.cc
index 8b49a26..aad9b3d 100644
--- a/video/send_statistics_proxy_unittest.cc
+++ b/video/send_statistics_proxy_unittest.cc
@@ -45,6 +45,16 @@
   codec_info.codecType = kVideoCodecVP8;
   return codec_info;
 }();
+
+const VideoStreamEncoderObserver::AdaptationSettings kScalingEnabled(true,
+                                                                     true);
+const VideoStreamEncoderObserver::AdaptationSettings kFramerateScalingDisabled(
+    true,
+    false);
+const VideoStreamEncoderObserver::AdaptationSettings kResolutionScalingDisabled(
+    false,
+    true);
+const VideoStreamEncoderObserver::AdaptationSettings kScalingDisabled;
 }  // namespace
 
 class SendStatisticsProxyTest : public ::testing::Test {
@@ -432,81 +442,86 @@
 }
 
 TEST_F(SendStatisticsProxyTest, GetCpuAdaptationStats) {
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
   EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
   EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
-  cpu_counts.num_framerate_reductions = 1;
-  cpu_counts.num_resolution_reductions = 0;
+  cpu_counts.fps_adaptations = 1;
+  cpu_counts.resolution_adaptations = 0;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
+      VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
       quality_counts);
   EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
   EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
-  cpu_counts.num_framerate_reductions = 0;
-  cpu_counts.num_resolution_reductions = 1;
+  cpu_counts.fps_adaptations = 0;
+  cpu_counts.resolution_adaptations = 1;
   statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
+      VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
       quality_counts);
   EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
   EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
-  cpu_counts.num_framerate_reductions = 1;
-  cpu_counts.num_resolution_reductions = absl::nullopt;
+  cpu_counts.fps_adaptations = 1;
+  statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
+                                              kResolutionScalingDisabled);
   statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
+      VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
       quality_counts);
   EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
   EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
-  cpu_counts.num_framerate_reductions = absl::nullopt;
-  cpu_counts.num_resolution_reductions = absl::nullopt;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
+                                              kScalingDisabled);
   statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
+      VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
       quality_counts);
   EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
   EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
 }
 
 TEST_F(SendStatisticsProxyTest, GetQualityAdaptationStats) {
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
-  quality_counts.num_framerate_reductions = 1;
-  quality_counts.num_resolution_reductions = 0;
+  quality_counts.fps_adaptations = 1;
+  quality_counts.resolution_adaptations = 0;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
+      VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
   EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
-  quality_counts.num_framerate_reductions = 0;
-  quality_counts.num_resolution_reductions = 1;
+  quality_counts.fps_adaptations = 0;
+  quality_counts.resolution_adaptations = 1;
   statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
+      VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
   EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
-  quality_counts.num_framerate_reductions = 1;
-  quality_counts.num_resolution_reductions = absl::nullopt;
+  quality_counts.fps_adaptations = 1;
+  statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
+                                              kResolutionScalingDisabled);
   statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
+      VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
   EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
-  quality_counts.num_framerate_reductions = absl::nullopt;
-  quality_counts.num_resolution_reductions = absl::nullopt;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
+                                              kScalingDisabled);
   statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
+      VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
 }
 
 TEST_F(SendStatisticsProxyTest, GetStatsReportsCpuAdaptChanges) {
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
   EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
 
-  cpu_counts.num_resolution_reductions = 1;
+  cpu_counts.resolution_adaptations = 1;
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
       quality_counts);
@@ -514,7 +529,7 @@
   EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
   EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
 
-  cpu_counts.num_resolution_reductions = 2;
+  cpu_counts.resolution_adaptations = 2;
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
       quality_counts);
@@ -525,11 +540,12 @@
 }
 
 TEST_F(SendStatisticsProxyTest, GetStatsReportsQualityAdaptChanges) {
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
 
-  quality_counts.num_framerate_reductions = 1;
+  quality_counts.fps_adaptations = 1;
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
@@ -537,7 +553,7 @@
   EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
   EXPECT_EQ(1, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
 
-  quality_counts.num_framerate_reductions = 0;
+  quality_counts.fps_adaptations = 0;
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
@@ -547,6 +563,77 @@
   EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
 }
 
+TEST_F(SendStatisticsProxyTest, TestAdaptationStatisticsMasking) {
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
+  EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
+  EXPECT_EQ(0, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
+
+  quality_counts.resolution_adaptations = 1;
+  statistics_proxy_->OnAdaptationChanged(
+      VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
+      quality_counts);
+  quality_counts.fps_adaptations = 1;
+  statistics_proxy_->OnAdaptationChanged(
+      VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
+      quality_counts);
+  cpu_counts.resolution_adaptations = 1;
+  statistics_proxy_->OnAdaptationChanged(
+      VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
+      quality_counts);
+  cpu_counts.fps_adaptations = 1;
+  statistics_proxy_->OnAdaptationChanged(
+      VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
+      quality_counts);
+  // We have 1 fps and resolution reduction for both cpu and quality
+  EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
+  EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
+  EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
+  EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
+  EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
+  EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
+
+  // Disable quality scaling. Expect quality scaling not limited.
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
+                                              kScalingDisabled);
+  EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
+  EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
+  EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
+  EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
+  EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
+  EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
+
+  // Disable framerate scaling.
+  statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
+                                              kFramerateScalingDisabled);
+  EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_framerate);
+  EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
+  EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_framerate);
+  EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
+  EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
+  EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
+
+  // Disable resolution scaling.
+  statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
+                                              kResolutionScalingDisabled);
+  EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
+  EXPECT_FALSE(statistics_proxy_->GetStats().bw_limited_resolution);
+  EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
+  EXPECT_FALSE(statistics_proxy_->GetStats().cpu_limited_resolution);
+  EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
+  EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
+
+  // Enable all
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
+  EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_framerate);
+  EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
+  EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_framerate);
+  EXPECT_TRUE(statistics_proxy_->GetStats().cpu_limited_resolution);
+  EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_quality_adapt_changes);
+  EXPECT_EQ(2, statistics_proxy_->GetStats().number_of_cpu_adapt_changes);
+}
+
 TEST_F(SendStatisticsProxyTest, AdaptChangesNotReported_AdaptationNotEnabled) {
   // First RTP packet sent.
   UpdateDataCounters(kFirstSsrc);
@@ -563,11 +650,7 @@
   // First RTP packet sent.
   UpdateDataCounters(kFirstSsrc);
   // Enable adaptation.
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   // Min runtime has not passed.
   fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000 - 1);
   statistics_proxy_.reset();
@@ -581,11 +664,7 @@
   // First RTP packet sent.
   UpdateDataCounters(kFirstSsrc);
   // Enable adaptation.
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   // Min runtime has passed.
   fake_clock_.AdvanceTimeMilliseconds(metrics::kMinRunTimeInSeconds * 1000);
   statistics_proxy_.reset();
@@ -603,11 +682,9 @@
   // First RTP packet sent.
   UpdateDataCounters(kFirstSsrc);
   // Enable adaptation.
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   // Adapt changes: 1, elapsed time: 10 sec => 6 per minute.
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
@@ -624,11 +701,9 @@
   // First RTP packet sent.
   UpdateDataCounters(kFirstSsrc);
   // Enable adaptation.
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   // Adapt changes: 1 (1 initial) = 0, elapsed time: 10 sec => 0 per minute.
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
@@ -646,23 +721,21 @@
   // First RTP packet sent.
   UpdateDataCounters(kFirstSsrc);
   // Enable adaptation.
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   // Adapt changes: 3 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
-  quality_counts.num_resolution_reductions = 1;
+  quality_counts.resolution_adaptations = 1;
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
   statistics_proxy_->OnInitialQualityResolutionAdaptDown();
-  quality_counts.num_resolution_reductions = 2;
+  quality_counts.resolution_adaptations = 2;
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
   statistics_proxy_->OnInitialQualityResolutionAdaptDown();
-  quality_counts.num_resolution_reductions = 3;
+  quality_counts.resolution_adaptations = 3;
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
@@ -678,11 +751,9 @@
   // First RTP packet sent.
   UpdateDataCounters(kFirstSsrc);
   // Enable adaptation.
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   // Adapt changes: 1 (2 initial) = 1, elapsed time: 10 sec => 6 per minute.
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
@@ -701,43 +772,42 @@
   // First RTP packet sent.
   UpdateDataCounters(kFirstSsrc);
   // Enable adaptation.
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
+  statistics_proxy_->ClearAdaptationStats();
   // Adapt changes: 8 (4 initial) = 4, elapsed time: 10 sec => 24 per minute.
-  quality_counts.num_resolution_reductions = 1;
+  quality_counts.resolution_adaptations = 1;
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
   statistics_proxy_->OnInitialQualityResolutionAdaptDown();
-  quality_counts.num_resolution_reductions = 2;
+  quality_counts.resolution_adaptations = 2;
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
   statistics_proxy_->OnInitialQualityResolutionAdaptDown();
-  quality_counts.num_resolution_reductions = 3;
+  quality_counts.resolution_adaptations = 3;
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
-  quality_counts.num_framerate_reductions = 1;
+  quality_counts.fps_adaptations = 1;
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
-  quality_counts.num_framerate_reductions = 0;
+  quality_counts.fps_adaptations = 0;
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
-  quality_counts.num_resolution_reductions = 2;  // Initial resolution up.
+  quality_counts.resolution_adaptations = 2;  // Initial resolution up.
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
-  quality_counts.num_resolution_reductions = 1;  // Initial resolution up.
+  quality_counts.resolution_adaptations = 1;  // Initial resolution up.
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
-  quality_counts.num_resolution_reductions = 0;
+  quality_counts.resolution_adaptations = 0;
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
@@ -755,25 +825,20 @@
   UpdateDataCounters(kFirstSsrc);
 
   // Disable quality adaptation.
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
-  quality_counts.num_framerate_reductions = absl::nullopt;
-  quality_counts.num_resolution_reductions = absl::nullopt;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
+                                              kScalingDisabled);
   fake_clock_.AdvanceTimeMilliseconds(10000);
 
   // Enable quality adaptation.
   // Adapt changes: 2, elapsed time: 20 sec.
-  quality_counts.num_framerate_reductions = 0;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  quality_counts.fps_adaptations = 0;
+  statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
+                                              kResolutionScalingDisabled);
   fake_clock_.AdvanceTimeMilliseconds(5000);
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
+                                              kResolutionScalingDisabled);
   fake_clock_.AdvanceTimeMilliseconds(9000);
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
@@ -784,32 +849,26 @@
       quality_counts);
 
   // Disable quality adaptation.
-  quality_counts.num_framerate_reductions = absl::nullopt;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
+                                              kScalingDisabled);
   fake_clock_.AdvanceTimeMilliseconds(30000);
 
   // Enable quality adaptation.
   // Adapt changes: 1, elapsed time: 10 sec.
-  quality_counts.num_resolution_reductions = 0;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  quality_counts.resolution_adaptations = 0;
+  statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
+                                              kFramerateScalingDisabled);
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
   fake_clock_.AdvanceTimeMilliseconds(10000);
 
   // Disable quality adaptation.
-  quality_counts.num_resolution_reductions = absl::nullopt;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
+                                              kScalingDisabled);
   fake_clock_.AdvanceTimeMilliseconds(5000);
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
+                                              kScalingDisabled);
   fake_clock_.AdvanceTimeMilliseconds(20000);
 
   // Adapt changes: 3, elapsed time: 30 sec => 6 per minute.
@@ -844,12 +903,10 @@
   UpdateDataCounters(kFirstSsrc);
 
   // Enable adaptation.
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
   // Adapt changes: 2, elapsed time: 20 sec.
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   fake_clock_.AdvanceTimeMilliseconds(20000);
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
@@ -886,12 +943,10 @@
   fake_clock_.AdvanceTimeMilliseconds(30000);
 
   // Enable adaptation.
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
   // Adapt changes: 1, elapsed time: 20 sec.
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   fake_clock_.AdvanceTimeMilliseconds(10000);
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
@@ -902,11 +957,8 @@
   fake_clock_.AdvanceTimeMilliseconds(10000);
 
   // Disable adaptation.
-  cpu_counts.num_framerate_reductions = absl::nullopt;
-  cpu_counts.num_resolution_reductions = absl::nullopt;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
+                                              kScalingDisabled);
   fake_clock_.AdvanceTimeMilliseconds(30000);
 
   // Suspend and resume video, stats time not started when scaling not enabled.
@@ -917,11 +969,9 @@
 
   // Enable adaptation.
   // Adapt changes: 1, elapsed time: 10 sec.
-  cpu_counts.num_framerate_reductions = 0;
-  cpu_counts.num_resolution_reductions = 0;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  cpu_counts.fps_adaptations = 0;
+  cpu_counts.resolution_adaptations = 0;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   fake_clock_.AdvanceTimeMilliseconds(10000);
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
@@ -943,11 +993,9 @@
   statistics_proxy_->OnSuspendChange(true);
 
   // Enable adaptation, stats time not started when suspended.
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   fake_clock_.AdvanceTimeMilliseconds(10000);
 
   // Resume video, stats time started.
@@ -969,11 +1017,9 @@
 TEST_F(SendStatisticsProxyTest, AdaptChangesStatsRestartsOnFirstSentPacket) {
   // Send first packet, adaptation enabled.
   // Elapsed time before first packet is sent should be excluded.
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   fake_clock_.AdvanceTimeMilliseconds(10000);
   UpdateDataCounters(kFirstSsrc);
 
@@ -994,17 +1040,12 @@
 
 TEST_F(SendStatisticsProxyTest, AdaptChangesStatsStartedAfterFirstSentPacket) {
   // Enable and disable adaptation.
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   fake_clock_.AdvanceTimeMilliseconds(60000);
-  cpu_counts.num_framerate_reductions = absl::nullopt;
-  cpu_counts.num_resolution_reductions = absl::nullopt;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  statistics_proxy_->UpdateAdaptationSettings(kScalingDisabled,
+                                              kScalingDisabled);
 
   // Send first packet, scaling disabled.
   // Elapsed time before first packet is sent should be excluded.
@@ -1012,10 +1053,9 @@
   fake_clock_.AdvanceTimeMilliseconds(60000);
 
   // Enable adaptation.
-  cpu_counts.num_resolution_reductions = 0;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  cpu_counts.resolution_adaptations = 0;
+  statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
+                                              kScalingDisabled);
   fake_clock_.AdvanceTimeMilliseconds(10000);
   UpdateDataCounters(kFirstSsrc);
 
@@ -1036,13 +1076,10 @@
 TEST_F(SendStatisticsProxyTest, AdaptChangesReportedAfterContentSwitch) {
   // First RTP packet sent, cpu adaptation enabled.
   UpdateDataCounters(kFirstSsrc);
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
-  quality_counts.num_framerate_reductions = absl::nullopt;
-  quality_counts.num_resolution_reductions = absl::nullopt;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
+                                              kScalingDisabled);
 
   // Adapt changes: 2, elapsed time: 15 sec => 8 per minute.
   statistics_proxy_->OnAdaptationChanged(
@@ -1067,9 +1104,8 @@
 
   // First RTP packet sent, scaling enabled.
   UpdateDataCounters(kFirstSsrc);
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled,
+                                              kScalingDisabled);
 
   // Adapt changes: 4, elapsed time: 120 sec => 2 per minute.
   statistics_proxy_->OnAdaptationChanged(
@@ -1100,11 +1136,11 @@
 
 TEST_F(SendStatisticsProxyTest,
        QualityLimitationReasonIsCpuWhenCpuIsResolutionLimited) {
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
 
-  cpu_counts.num_resolution_reductions = 1;
-
+  cpu_counts.resolution_adaptations = 1;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
       quality_counts);
@@ -1115,11 +1151,12 @@
 
 TEST_F(SendStatisticsProxyTest,
        QualityLimitationReasonIsCpuWhenCpuIsFramerateLimited) {
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
 
-  cpu_counts.num_framerate_reductions = 1;
+  cpu_counts.fps_adaptations = 1;
 
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
       quality_counts);
@@ -1130,11 +1167,12 @@
 
 TEST_F(SendStatisticsProxyTest,
        QualityLimitationReasonIsBandwidthWhenQualityIsResolutionLimited) {
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
 
-  quality_counts.num_resolution_reductions = 1;
+  quality_counts.resolution_adaptations = 1;
 
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
@@ -1145,11 +1183,12 @@
 
 TEST_F(SendStatisticsProxyTest,
        QualityLimitationReasonIsBandwidthWhenQualityIsFramerateLimited) {
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
 
-  quality_counts.num_framerate_reductions = 1;
+  quality_counts.fps_adaptations = 1;
 
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
@@ -1160,11 +1199,12 @@
 
 TEST_F(SendStatisticsProxyTest,
        QualityLimitationReasonIsBandwidthWhenBothCpuAndQualityIsLimited) {
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
 
-  cpu_counts.num_resolution_reductions = 1;
-  quality_counts.num_resolution_reductions = 1;
+  cpu_counts.resolution_adaptations = 1;
+  quality_counts.resolution_adaptations = 1;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
 
   // Even if the last adaptation reason is kCpu, if the counters indicate being
   // both CPU and quality (=bandwidth) limited, kBandwidth takes precedence.
@@ -1177,19 +1217,20 @@
 }
 
 TEST_F(SendStatisticsProxyTest, QualityLimitationReasonIsNoneWhenNotLimited) {
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
 
   // Observe a limitation due to CPU. This makes sure the test doesn't pass
   // due to "none" being the default value.
-  cpu_counts.num_resolution_reductions = 1;
+  cpu_counts.resolution_adaptations = 1;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
       quality_counts);
   // Go back to not being limited.
-  cpu_counts.num_resolution_reductions = 0;
+  cpu_counts.resolution_adaptations = 0;
   statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
+      VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
       quality_counts);
 
   EXPECT_EQ(QualityLimitationReason::kNone,
@@ -1197,27 +1238,28 @@
 }
 
 TEST_F(SendStatisticsProxyTest, QualityLimitationDurationIncreasesWithTime) {
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
 
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   // Not limited for 3000 ms
   fake_clock_.AdvanceTimeMilliseconds(3000);
   // CPU limited for 2000 ms
-  cpu_counts.num_resolution_reductions = 1;
+  cpu_counts.resolution_adaptations = 1;
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
       quality_counts);
   fake_clock_.AdvanceTimeMilliseconds(2000);
   // Bandwidth limited for 1000 ms
-  cpu_counts.num_resolution_reductions = 0;
-  quality_counts.num_resolution_reductions = 1;
+  cpu_counts.resolution_adaptations = 0;
+  quality_counts.resolution_adaptations = 1;
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
   fake_clock_.AdvanceTimeMilliseconds(1000);
   // CPU limited for another 2000 ms
-  cpu_counts.num_resolution_reductions = 1;
-  quality_counts.num_resolution_reductions = 0;
+  cpu_counts.resolution_adaptations = 1;
+  quality_counts.resolution_adaptations = 0;
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
       quality_counts);
@@ -1624,12 +1666,8 @@
 }
 
 TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramNotUpdatedWhenDisabled) {
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
-  cpu_counts.num_resolution_reductions = absl::nullopt;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  statistics_proxy_->UpdateAdaptationSettings(kResolutionScalingDisabled,
+                                              kResolutionScalingDisabled);
 
   for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
     statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
@@ -1640,17 +1678,15 @@
 }
 
 TEST_F(SendStatisticsProxyTest, CpuLimitedHistogramUpdated) {
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
-  cpu_counts.num_resolution_reductions = 0;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
+  cpu_counts.resolution_adaptations = 0;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
 
   for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
     statistics_proxy_->OnIncomingFrame(kWidth, kHeight);
 
-  cpu_counts.num_resolution_reductions = 1;
+  cpu_counts.resolution_adaptations = 1;
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kCpu, cpu_counts,
       quality_counts);
@@ -2033,12 +2069,8 @@
 
 TEST_F(SendStatisticsProxyTest,
        QualityLimitedHistogramsNotUpdatedWhenDisabled) {
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
-  quality_counts.num_resolution_reductions = absl::nullopt;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
+                                              kScalingDisabled);
   EncodedImage encoded_image;
   encoded_image.SetSpatialIndex(0);
   for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
@@ -2054,12 +2086,7 @@
 
 TEST_F(SendStatisticsProxyTest,
        QualityLimitedHistogramsUpdatedWhenEnabled_NoResolutionDownscale) {
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
-  quality_counts.num_resolution_reductions = 0;
-  statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
-      quality_counts);
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   EncodedImage encoded_image;
   encoded_image.SetSpatialIndex(0);
   for (int i = 0; i < SendStatisticsProxy::kMinRequiredMetricsSamples; ++i)
@@ -2079,11 +2106,12 @@
 TEST_F(SendStatisticsProxyTest,
        QualityLimitedHistogramsUpdatedWhenEnabled_TwoResolutionDownscales) {
   const int kDownscales = 2;
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
-  quality_counts.num_resolution_reductions = kDownscales;
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
+  quality_counts.resolution_adaptations = kDownscales;
+  statistics_proxy_->UpdateAdaptationSettings(kScalingEnabled, kScalingEnabled);
   statistics_proxy_->OnAdaptationChanged(
-      VideoStreamEncoderObserver::AdaptationReason::kNone, cpu_counts,
+      VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
   EncodedImage encoded_image;
   encoded_image.SetSpatialIndex(0);
@@ -2126,9 +2154,11 @@
   encoded_image._encodedHeight = kHeight / 2;
 
   // Resolution scaled due to quality.
-  SendStatisticsProxy::AdaptationSteps cpu_counts;
-  SendStatisticsProxy::AdaptationSteps quality_counts;
-  quality_counts.num_resolution_reductions = 1;
+  VideoAdaptationCounters cpu_counts;
+  VideoAdaptationCounters quality_counts;
+  quality_counts.resolution_adaptations = 1;
+  statistics_proxy_->UpdateAdaptationSettings(kFramerateScalingDisabled,
+                                              kFramerateScalingDisabled);
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
@@ -2136,7 +2166,7 @@
   EXPECT_TRUE(statistics_proxy_->GetStats().bw_limited_resolution);
 
   // Adapt up.
-  quality_counts.num_resolution_reductions = 0;
+  quality_counts.resolution_adaptations = 0;
   statistics_proxy_->OnAdaptationChanged(
       VideoStreamEncoderObserver::AdaptationReason::kQuality, cpu_counts,
       quality_counts);
diff --git a/video/video_stream_encoder_unittest.cc b/video/video_stream_encoder_unittest.cc
index bb85776..d3baa37 100644
--- a/video/video_stream_encoder_unittest.cc
+++ b/video/video_stream_encoder_unittest.cc
@@ -3959,6 +3959,7 @@
   // Reset encoder for field trials to take effect.
   VideoEncoderConfig config = video_encoder_config_.Copy();
   config.max_bitrate_bps = kTargetBitrateBps;
+  DataRate max_bitrate = DataRate::BitsPerSec(config.max_bitrate_bps);
   ConfigureEncoder(std::move(config));
   fake_encoder_.SetQp(kQpLow);
 
@@ -3985,10 +3986,8 @@
   EXPECT_LT(source.sink_wants().max_pixel_count, kWidth * kHeight);
 
   // Increase bitrate to encoder max.
-  video_stream_encoder_->OnBitrateUpdated(
-      DataRate::BitsPerSec(config.max_bitrate_bps),
-      DataRate::BitsPerSec(config.max_bitrate_bps),
-      DataRate::BitsPerSec(config.max_bitrate_bps), 0, 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(max_bitrate, max_bitrate, max_bitrate,
+                                          0, 0, 0);
 
   // Insert frames and advance |min_duration_ms|.
   for (size_t i = 1; i <= 10; i++) {