Compare adapt up/down request with sink_wants_ in VideoSourceProxy methods to make sure it is higher/lower than last request.
Add methods RestrictFramerate, IncreaseFramerate.

To be used by kBalanced mode.

This CL is split from: https://codereview.webrtc.org/2887303003/

BUG=webrtc:7607

Review-Url: https://codereview.webrtc.org/2903563002
Cr-Commit-Position: refs/heads/master@{#18463}
diff --git a/webrtc/video/vie_encoder.cc b/webrtc/video/vie_encoder.cc
index b56bbf5..203d1c4 100644
--- a/webrtc/video/vie_encoder.cc
+++ b/webrtc/video/vie_encoder.cc
@@ -230,54 +230,50 @@
   bool RequestResolutionLowerThan(int pixel_count) {
     // Called on the encoder task queue.
     rtc::CritScope lock(&crit_);
-    if (!IsResolutionScalingEnabled(degradation_preference_)) {
+    if (!source_ || !IsResolutionScalingEnabled(degradation_preference_)) {
       // This can happen since |degradation_preference_| is set on libjingle's
       // worker thread but the adaptation is done on the encoder task queue.
       return false;
     }
-    // The input video frame size will have a resolution with less than or
-    // equal to |max_pixel_count| depending on how the source can scale the
-    // input frame size.
+    // The input video frame size will have a resolution less than or equal to
+    // |max_pixel_count| depending on how the source can scale the frame size.
     const int pixels_wanted = (pixel_count * 3) / 5;
-    if (pixels_wanted < kMinPixelsPerFrame)
+    if (pixels_wanted < kMinPixelsPerFrame ||
+        pixels_wanted >= sink_wants_.max_pixel_count) {
       return false;
-
+    }
+    LOG(LS_INFO) << "Scaling down resolution, max pixels: " << pixels_wanted;
     sink_wants_.max_pixel_count = pixels_wanted;
     sink_wants_.target_pixel_count = rtc::Optional<int>();
-    if (source_)
-      source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants());
+    source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants());
     return true;
   }
 
-  void RequestFramerateLowerThan(int framerate_fps) {
+  bool RequestFramerateLowerThan(int fps) {
     // Called on the encoder task queue.
-    rtc::CritScope lock(&crit_);
-    if (!IsFramerateScalingEnabled(degradation_preference_)) {
-      // This can happen since |degradation_preference_| is set on libjingle's
-      // worker thread but the adaptation is done on the encoder task queue.
-      return;
-    }
-    // The input video frame rate will be scaled down to 2/3 of input fps,
-    // rounding down.
-    const int framerate_wanted =
-        std::max(kMinFramerateFps, (framerate_fps * 2) / 3);
-    sink_wants_.max_framerate_fps = framerate_wanted;
-    if (source_)
-      source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants());
+    // The input video frame rate will be scaled down to 2/3, rounding down.
+    return RestrictFramerate((fps * 2) / 3);
   }
 
-  void RequestHigherResolutionThan(int pixel_count) {
+  bool RequestHigherResolutionThan(int pixel_count) {
+    // Called on the encoder task queue.
     rtc::CritScope lock(&crit_);
-    if (!IsResolutionScalingEnabled(degradation_preference_)) {
+    if (!source_ || !IsResolutionScalingEnabled(degradation_preference_)) {
       // This can happen since |degradation_preference_| is set on libjingle's
       // worker thread but the adaptation is done on the encoder task queue.
-      return;
+      return false;
     }
+    int max_pixels_wanted = pixel_count;
+    if (max_pixels_wanted != std::numeric_limits<int>::max())
+      max_pixels_wanted = pixel_count * 4;
 
-    if (pixel_count == std::numeric_limits<int>::max()) {
+    if (max_pixels_wanted <= sink_wants_.max_pixel_count)
+      return false;
+
+    sink_wants_.max_pixel_count = max_pixels_wanted;
+    if (max_pixels_wanted == std::numeric_limits<int>::max()) {
       // Remove any constraints.
       sink_wants_.target_pixel_count.reset();
-      sink_wants_.max_pixel_count = std::numeric_limits<int>::max();
     } else {
       // On step down we request at most 3/5 the pixel count of the previous
       // resolution, so in order to take "one step up" we request a resolution
@@ -287,31 +283,52 @@
       // most four time the current number of pixels.
       sink_wants_.target_pixel_count =
           rtc::Optional<int>((pixel_count * 5) / 3);
-      sink_wants_.max_pixel_count = pixel_count * 4;
     }
-    if (source_)
-      source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants());
+    LOG(LS_INFO) << "Scaling up resolution, max pixels: " << max_pixels_wanted;
+    source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants());
+    return true;
   }
 
-  void RequestHigherFramerateThan(int framerate_fps) {
+  bool RequestHigherFramerateThan(int fps) {
+    // Called on the encoder task queue.
+    // The input frame rate will be scaled up to the last step, with rounding.
+    int framerate_wanted = fps;
+    if (fps != std::numeric_limits<int>::max())
+      framerate_wanted = (fps * 3) / 2;
+
+    return IncreaseFramerate(framerate_wanted);
+  }
+
+  bool RestrictFramerate(int fps) {
     // Called on the encoder task queue.
     rtc::CritScope lock(&crit_);
-    if (!IsFramerateScalingEnabled(degradation_preference_)) {
-      // This can happen since |degradation_preference_| is set on libjingle's
-      // worker thread but the adaptation is done on the encoder task queue.
-      return;
-    }
-    if (framerate_fps == std::numeric_limits<int>::max()) {
-      // Remove any restrains.
-      sink_wants_.max_framerate_fps = std::numeric_limits<int>::max();
-    } else {
-      // The input video frame rate will be scaled up to the last step, with
-      // rounding.
-      const int framerate_wanted = (framerate_fps * 3) / 2;
-      sink_wants_.max_framerate_fps = framerate_wanted;
-    }
-    if (source_)
-      source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants());
+    if (!source_ || !IsFramerateScalingEnabled(degradation_preference_))
+      return false;
+
+    const int fps_wanted = std::max(kMinFramerateFps, fps);
+    if (fps_wanted >= sink_wants_.max_framerate_fps)
+      return false;
+
+    LOG(LS_INFO) << "Scaling down framerate: " << fps_wanted;
+    sink_wants_.max_framerate_fps = fps_wanted;
+    source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants());
+    return true;
+  }
+
+  bool IncreaseFramerate(int fps) {
+    // Called on the encoder task queue.
+    rtc::CritScope lock(&crit_);
+    if (!source_ || !IsFramerateScalingEnabled(degradation_preference_))
+      return false;
+
+    const int fps_wanted = std::max(kMinFramerateFps, fps);
+    if (fps_wanted <= sink_wants_.max_framerate_fps)
+      return false;
+
+    LOG(LS_INFO) << "Scaling up framerate: " << fps_wanted;
+    sink_wants_.max_framerate_fps = fps_wanted;
+    source_->AddOrUpdateSink(vie_encoder_, GetActiveSinkWants());
+    return true;
   }
 
  private:
@@ -827,17 +844,19 @@
     case VideoSendStream::DegradationPreference::kBalanced:
       FALLTHROUGH();
     case VideoSendStream::DegradationPreference::kMaintainFramerate:
+      // Scale down resolution.
       if (!source_proxy_->RequestResolutionLowerThan(
               adaptation_request.input_pixel_count_)) {
         return;
       }
-      LOG(LS_INFO) << "Scaling down resolution.";
       GetAdaptCounter().IncrementResolution(reason, 1);
       break;
     case VideoSendStream::DegradationPreference::kMaintainResolution:
-      source_proxy_->RequestFramerateLowerThan(
-          adaptation_request.framerate_fps_);
-      LOG(LS_INFO) << "Scaling down framerate.";
+      // Scale down framerate.
+      if (!source_proxy_->RequestFramerateLowerThan(
+              adaptation_request.framerate_fps_)) {
+        return;
+      }
       GetAdaptCounter().IncrementFramerate(reason, 1);
       break;
     case VideoSendStream::DegradationPreference::kDegradationDisabled:
@@ -892,30 +911,30 @@
   switch (degradation_preference_) {
     case VideoSendStream::DegradationPreference::kBalanced:
       FALLTHROUGH();
-    case VideoSendStream::DegradationPreference::kMaintainFramerate:
-      if (adapt_counter.TotalCount() == 1) {
+    case VideoSendStream::DegradationPreference::kMaintainFramerate: {
+      // Scale up resolution.
+      int pixel_count = adaptation_request.input_pixel_count_;
+      if (adapt_counter.ResolutionCount() == 1) {
         LOG(LS_INFO) << "Removing resolution down-scaling setting.";
-        source_proxy_->RequestHigherResolutionThan(
-            std::numeric_limits<int>::max());
-      } else {
-        source_proxy_->RequestHigherResolutionThan(
-            adaptation_request.input_pixel_count_);
-        LOG(LS_INFO) << "Scaling up resolution.";
+        pixel_count = std::numeric_limits<int>::max();
       }
+      if (!source_proxy_->RequestHigherResolutionThan(pixel_count))
+        return;
       GetAdaptCounter().IncrementResolution(reason, -1);
       break;
-    case VideoSendStream::DegradationPreference::kMaintainResolution:
-      if (adapt_counter.TotalCount() == 1) {
+    }
+    case VideoSendStream::DegradationPreference::kMaintainResolution: {
+      // Scale up framerate.
+      int fps = adaptation_request.framerate_fps_;
+      if (adapt_counter.FramerateCount() == 1) {
         LOG(LS_INFO) << "Removing framerate down-scaling setting.";
-        source_proxy_->RequestHigherFramerateThan(
-            std::numeric_limits<int>::max());
-      } else {
-        source_proxy_->RequestHigherFramerateThan(
-            adaptation_request.framerate_fps_);
-        LOG(LS_INFO) << "Scaling up framerate.";
+        fps = std::numeric_limits<int>::max();
       }
+      if (!source_proxy_->RequestHigherFramerateThan(fps))
+        return;
       GetAdaptCounter().IncrementFramerate(reason, -1);
       break;
+    }
     case VideoSendStream::DegradationPreference::kDegradationDisabled:
       RTC_NOTREACHED();
   }
diff --git a/webrtc/video/vie_encoder_unittest.cc b/webrtc/video/vie_encoder_unittest.cc
index eb39bf7..7a54fbe 100644
--- a/webrtc/video/vie_encoder_unittest.cc
+++ b/webrtc/video/vie_encoder_unittest.cc
@@ -1048,8 +1048,8 @@
   video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
   sink_.WaitForEncodedFrame(1);
   VideoSendStream::Stats stats = stats_proxy_->GetStats();
-  EXPECT_FALSE(stats.cpu_limited_resolution);
   EXPECT_FALSE(stats.bw_limited_resolution);
+  EXPECT_FALSE(stats.bw_limited_framerate);
   EXPECT_EQ(0, stats.number_of_quality_adapt_changes);
 
   // Set new source with adaptation still enabled.
@@ -1060,8 +1060,8 @@
   new_video_source.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
   sink_.WaitForEncodedFrame(2);
   stats = stats_proxy_->GetStats();
-  EXPECT_FALSE(stats.cpu_limited_resolution);
   EXPECT_FALSE(stats.bw_limited_resolution);
+  EXPECT_FALSE(stats.bw_limited_framerate);
   EXPECT_EQ(0, stats.number_of_quality_adapt_changes);
 
   // Trigger adapt down.
@@ -1069,8 +1069,8 @@
   new_video_source.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
   sink_.WaitForEncodedFrame(3);
   stats = stats_proxy_->GetStats();
-  EXPECT_FALSE(stats.cpu_limited_resolution);
   EXPECT_TRUE(stats.bw_limited_resolution);
+  EXPECT_FALSE(stats.bw_limited_framerate);
   EXPECT_EQ(1, stats.number_of_quality_adapt_changes);
 
   // Set new source with adaptation still enabled.
@@ -1080,8 +1080,8 @@
   new_video_source.IncomingCapturedFrame(CreateFrame(4, kWidth, kHeight));
   sink_.WaitForEncodedFrame(4);
   stats = stats_proxy_->GetStats();
-  EXPECT_FALSE(stats.cpu_limited_resolution);
   EXPECT_TRUE(stats.bw_limited_resolution);
+  EXPECT_FALSE(stats.bw_limited_framerate);
   EXPECT_EQ(1, stats.number_of_quality_adapt_changes);
 
   // Disable resolution scaling.
@@ -1092,8 +1092,8 @@
   new_video_source.IncomingCapturedFrame(CreateFrame(5, kWidth, kHeight));
   sink_.WaitForEncodedFrame(5);
   stats = stats_proxy_->GetStats();
-  EXPECT_FALSE(stats.cpu_limited_resolution);
   EXPECT_FALSE(stats.bw_limited_resolution);
+  EXPECT_FALSE(stats.bw_limited_framerate);
   EXPECT_EQ(1, stats.number_of_quality_adapt_changes);
   EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
 
@@ -1154,6 +1154,7 @@
   sink_.WaitForEncodedFrame(sequence++);
   VideoSendStream::Stats stats = stats_proxy_->GetStats();
   EXPECT_FALSE(stats.cpu_limited_resolution);
+  EXPECT_FALSE(stats.cpu_limited_framerate);
   EXPECT_EQ(0, stats.number_of_cpu_adapt_changes);
 
   // Trigger CPU overuse, should now adapt down.
@@ -1162,6 +1163,7 @@
   sink_.WaitForEncodedFrame(sequence++);
   stats = stats_proxy_->GetStats();
   EXPECT_TRUE(stats.cpu_limited_resolution);
+  EXPECT_FALSE(stats.cpu_limited_framerate);
   EXPECT_EQ(1, stats.number_of_cpu_adapt_changes);
 
   // Set new source with adaptation still enabled.
@@ -1219,6 +1221,7 @@
 
   stats = stats_proxy_->GetStats();
   EXPECT_FALSE(stats.cpu_limited_resolution);
+  EXPECT_FALSE(stats.cpu_limited_framerate);
   EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
 
   // Try to trigger overuse. Should not succeed.
@@ -1228,6 +1231,7 @@
 
   stats = stats_proxy_->GetStats();
   EXPECT_FALSE(stats.cpu_limited_resolution);
+  EXPECT_FALSE(stats.cpu_limited_framerate);
   EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
 
   // Switch back the source with resolution adaptation enabled.
@@ -1238,6 +1242,7 @@
   sink_.WaitForEncodedFrame(sequence++);
   stats = stats_proxy_->GetStats();
   EXPECT_TRUE(stats.cpu_limited_resolution);
+  EXPECT_FALSE(stats.cpu_limited_framerate);
   EXPECT_EQ(2, stats.number_of_cpu_adapt_changes);
 
   // Trigger CPU normal usage.
@@ -1246,6 +1251,7 @@
   sink_.WaitForEncodedFrame(sequence++);
   stats = stats_proxy_->GetStats();
   EXPECT_FALSE(stats.cpu_limited_resolution);
+  EXPECT_FALSE(stats.cpu_limited_framerate);
   EXPECT_EQ(3, stats.number_of_cpu_adapt_changes);
 
   // Back to the source with adaptation off, set it back to maintain-resolution.
@@ -1256,8 +1262,9 @@
       CreateFrame(sequence, kWidth, kHeight));
   sink_.WaitForEncodedFrame(sequence++);
   stats = stats_proxy_->GetStats();
-  // Disabled, since we previously switched the source too disabled.
+  // Disabled, since we previously switched the source to disabled.
   EXPECT_FALSE(stats.cpu_limited_resolution);
+  EXPECT_TRUE(stats.cpu_limited_framerate);
   EXPECT_EQ(3, stats.number_of_cpu_adapt_changes);
 
   // Trigger CPU normal usage.
@@ -1267,6 +1274,7 @@
   sink_.WaitForEncodedFrame(sequence++);
   stats = stats_proxy_->GetStats();
   EXPECT_FALSE(stats.cpu_limited_resolution);
+  EXPECT_FALSE(stats.cpu_limited_framerate);
   EXPECT_EQ(4, stats.number_of_cpu_adapt_changes);
   EXPECT_EQ(0, stats.number_of_quality_adapt_changes);