Increase test coverage of InitialFrameDropper vs. RequestedResolution

Bug: b/364252657
Change-Id: I4924428c3f002a168eea12f111cb13890cad19f9
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/362220
Reviewed-by: Jonas Oreland <jonaso@webrtc.org>
Commit-Queue: Jonas Oreland <jonaso@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Ilya Nikolaevskiy <ilnik@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#43011}
diff --git a/video/video_stream_encoder_unittest.cc b/video/video_stream_encoder_unittest.cc
index 46df928..af6b32a 100644
--- a/video/video_stream_encoder_unittest.cc
+++ b/video/video_stream_encoder_unittest.cc
@@ -6218,25 +6218,87 @@
   video_stream_encoder_->Stop();
 }
 
-TEST_F(VideoStreamEncoderTest,
+enum class FrameResolutionChangeMethod {
+  MODIFY_SOURCE,
+  MODIFY_REQUESTED_RESOLUTION,
+};
+class VideoStreamEncoderInitialFrameDropperTest
+    : public VideoStreamEncoderTest,
+      public ::testing::WithParamInterface<FrameResolutionChangeMethod> {
+ public:
+  VideoStreamEncoderInitialFrameDropperTest()
+      : VideoStreamEncoderTest(), frame_resolution_change_method_(GetParam()) {}
+
+  void SetUp() override {
+    VideoStreamEncoderTest::SetUp();
+    if (frame_resolution_change_method_ ==
+        FrameResolutionChangeMethod::MODIFY_REQUESTED_RESOLUTION) {
+      video_encoder_config_.video_stream_factory = nullptr;
+    }
+  }
+
+ protected:
+  const FrameResolutionChangeMethod frame_resolution_change_method_;
+};
+
+INSTANTIATE_TEST_SUITE_P(
+    VideoStreamEncoderInitialFrameDropperTest,
+    VideoStreamEncoderInitialFrameDropperTest,
+    ::testing::Values(
+        FrameResolutionChangeMethod::MODIFY_SOURCE,
+        FrameResolutionChangeMethod::MODIFY_REQUESTED_RESOLUTION));
+
+TEST_P(VideoStreamEncoderInitialFrameDropperTest,
        InitialFrameDropActivatesWhenResolutionIncreases) {
   const int kWidth = 640;
   const int kHeight = 360;
 
+  const int kSmallWidth = 640 / 2;
+  const int kSmallHeight = 360 / 2;
+
+  int captureWidth;
+  int captureHeight;
+  if (frame_resolution_change_method_ ==
+      FrameResolutionChangeMethod::MODIFY_REQUESTED_RESOLUTION) {
+    captureWidth = kWidth;
+    captureHeight = kHeight;
+    ASSERT_THAT(video_encoder_config_.simulcast_layers, SizeIs(1));
+    video_encoder_config_.simulcast_layers[0].requested_resolution.emplace(
+        Resolution({.width = kSmallWidth, .height = kSmallHeight}));
+    video_stream_encoder_->ConfigureEncoder(video_encoder_config_.Copy(),
+                                            kMaxPayloadLength);
+  } else {
+    captureWidth = kSmallWidth;
+    captureHeight = kSmallHeight;
+  }
+
   video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
       kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
-  video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth / 2, kHeight / 2));
+  video_source_.IncomingCapturedFrame(
+      CreateFrame(1, captureWidth, captureHeight));
   // Frame should not be dropped.
   WaitForEncodedFrame(1);
 
   video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
       kLowTargetBitrate, kLowTargetBitrate, kLowTargetBitrate, 0, 0, 0);
-  video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth / 2, kHeight / 2));
+  video_source_.IncomingCapturedFrame(
+      CreateFrame(2, captureWidth, captureHeight));
   // Frame should not be dropped, bitrate not too low for frame.
   WaitForEncodedFrame(2);
 
   // Incoming resolution increases.
-  video_source_.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
+  if (frame_resolution_change_method_ ==
+      FrameResolutionChangeMethod::MODIFY_REQUESTED_RESOLUTION) {
+    video_encoder_config_.simulcast_layers[0].requested_resolution.emplace(
+        Resolution({.width = kWidth, .height = kHeight}));
+    video_stream_encoder_->ConfigureEncoder(video_encoder_config_.Copy(),
+                                            kMaxPayloadLength);
+  } else {
+    captureWidth = kWidth;
+    captureHeight = kHeight;
+  }
+  video_source_.IncomingCapturedFrame(
+      CreateFrame(3, captureWidth, captureHeight));
   // Expect to drop this frame, bitrate too low for frame.
   ExpectDroppedFrame();
 
@@ -6246,67 +6308,8 @@
   video_stream_encoder_->Stop();
 }
 
-TEST_F(VideoStreamEncoderTest, InitialFrameDropIsNotReactivatedWhenAdaptingUp) {
-  const int kWidth = 640;
-  const int kHeight = 360;
-  // So that quality scaling doesn't happen by itself.
-  fake_encoder_.SetQp(kQpHigh);
-
-  AdaptingFrameForwarder source(&time_controller_);
-  source.set_adaptation_enabled(true);
-  video_stream_encoder_->SetSource(
-      &source, webrtc::DegradationPreference::MAINTAIN_FRAMERATE);
-
-  int timestamp = 1;
-
-  video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
-      kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
-  source.IncomingCapturedFrame(CreateFrame(timestamp, kWidth, kHeight));
-  WaitForEncodedFrame(timestamp);
-  timestamp += 9000;
-  // Long pause to disable all first BWE drop logic.
-  AdvanceTime(TimeDelta::Millis(1000));
-
-  video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
-      kLowTargetBitrate, kLowTargetBitrate, kLowTargetBitrate, 0, 0, 0);
-  source.IncomingCapturedFrame(CreateFrame(timestamp, kWidth, kHeight));
-  // Not dropped frame, as initial frame drop is disabled by now.
-  WaitForEncodedFrame(timestamp);
-  timestamp += 9000;
-  AdvanceTime(TimeDelta::Millis(100));
-
-  // Quality adaptation down.
-  video_stream_encoder_->TriggerQualityLow();
-
-  // Adaptation has an effect.
-  EXPECT_TRUE_WAIT(source.sink_wants().max_pixel_count < kWidth * kHeight,
-                   5000);
-
-  // Frame isn't dropped as initial frame dropper is disabled.
-  source.IncomingCapturedFrame(CreateFrame(timestamp, kWidth, kHeight));
-  WaitForEncodedFrame(timestamp);
-  timestamp += 9000;
-  AdvanceTime(TimeDelta::Millis(100));
-
-  // Quality adaptation up.
-  video_stream_encoder_->TriggerQualityHigh();
-
-  // Adaptation has an effect.
-  EXPECT_TRUE_WAIT(source.sink_wants().max_pixel_count > kWidth * kHeight,
-                   5000);
-
-  source.IncomingCapturedFrame(CreateFrame(timestamp, kWidth, kHeight));
-  // Frame should not be dropped, as initial framedropper is off.
-  WaitForEncodedFrame(timestamp);
-
-  video_stream_encoder_->Stop();
-}
-
-// Same test as above but setting resolution using `requested_resolution`, which
-// does affect the number of ReconfigureEncoder() requiring extra care not to
-// reactivate InitialFrameDrop.
-TEST_F(VideoStreamEncoderTest,
-       InitialFrameDropIsNotReactivatedWhenAdaptingUp_RequestedResolution) {
+TEST_P(VideoStreamEncoderInitialFrameDropperTest,
+       InitialFrameDropIsNotReactivatedWhenAdaptingUp) {
   const int kWidth = 640;
   const int kHeight = 360;
   // So that quality scaling doesn't happen by itself.
@@ -6321,11 +6324,14 @@
 
   // By using the `requested_resolution` API, ReconfigureEncoder() gets
   // triggered from VideoStreamEncoder::OnVideoSourceRestrictionsUpdated().
-  ASSERT_THAT(video_encoder_config_.simulcast_layers, SizeIs(1));
-  video_encoder_config_.simulcast_layers[0].requested_resolution.emplace(
-      Resolution({.width = kWidth, .height = kHeight}));
-  video_stream_encoder_->ConfigureEncoder(video_encoder_config_.Copy(),
-                                          kMaxPayloadLength);
+  if (frame_resolution_change_method_ ==
+      FrameResolutionChangeMethod::MODIFY_REQUESTED_RESOLUTION) {
+    ASSERT_THAT(video_encoder_config_.simulcast_layers, SizeIs(1));
+    video_encoder_config_.simulcast_layers[0].requested_resolution.emplace(
+        Resolution({.width = kWidth, .height = kHeight}));
+    video_stream_encoder_->ConfigureEncoder(video_encoder_config_.Copy(),
+                                            kMaxPayloadLength);
+  }
 
   video_stream_encoder_->OnBitrateUpdatedAndWaitForManagedResources(
       kTargetBitrate, kTargetBitrate, kTargetBitrate, 0, 0, 0);
@@ -6370,7 +6376,7 @@
   video_stream_encoder_->Stop();
 }
 
-TEST_F(VideoStreamEncoderTest,
+TEST_P(VideoStreamEncoderInitialFrameDropperTest,
        FrameDroppedWhenResolutionIncreasesAndLinkAllocationIsLow) {
   const int kMinStartBps360p = 222000;
   fake_encoder_.SetResolutionBitrateLimits(
@@ -6383,12 +6389,48 @@
       DataRate::BitsPerSec(kMinStartBps360p - 1),  // stable_target_bitrate
       DataRate::BitsPerSec(kMinStartBps360p - 1),  // link_allocation
       0, 0, 0);
+
+  const int kWidth = 640;
+  const int kHeight = 360;
+
+  const int kSmallWidth = 640 / 2;
+  const int kSmallHeight = 360 / 2;
+
+  int captureWidth;
+  int captureHeight;
+  if (frame_resolution_change_method_ ==
+      FrameResolutionChangeMethod::MODIFY_REQUESTED_RESOLUTION) {
+    captureWidth = kWidth;
+    captureHeight = kHeight;
+    ASSERT_THAT(video_encoder_config_.simulcast_layers, SizeIs(1));
+    video_encoder_config_.simulcast_layers[0].requested_resolution.emplace(
+        Resolution({.width = kSmallWidth, .height = kSmallHeight}));
+    video_stream_encoder_->ConfigureEncoder(video_encoder_config_.Copy(),
+                                            kMaxPayloadLength);
+  } else {
+    captureWidth = kSmallWidth;
+    captureHeight = kSmallHeight;
+  }
+
   // Frame should not be dropped, bitrate not too low for frame.
-  video_source_.IncomingCapturedFrame(CreateFrame(1, 320, 180));
+  video_source_.IncomingCapturedFrame(
+      CreateFrame(1, captureWidth, captureHeight));
   WaitForEncodedFrame(1);
 
   // Incoming resolution increases, initial frame drop activates.
   // Frame should be dropped, link allocation too low for frame.
+  if (frame_resolution_change_method_ ==
+      FrameResolutionChangeMethod::MODIFY_REQUESTED_RESOLUTION) {
+    ASSERT_THAT(video_encoder_config_.simulcast_layers, SizeIs(1));
+    video_encoder_config_.simulcast_layers[0].requested_resolution.emplace(
+        Resolution({.width = kWidth, .height = kHeight}));
+    video_stream_encoder_->ConfigureEncoder(video_encoder_config_.Copy(),
+                                            kMaxPayloadLength);
+  } else {
+    captureWidth = kWidth;
+    captureHeight = kHeight;
+  }
+
   video_source_.IncomingCapturedFrame(CreateFrame(2, 640, 360));
   ExpectDroppedFrame();
 
@@ -6398,7 +6440,7 @@
   video_stream_encoder_->Stop();
 }
 
-TEST_F(VideoStreamEncoderTest,
+TEST_P(VideoStreamEncoderInitialFrameDropperTest,
        FrameNotDroppedWhenResolutionIncreasesAndLinkAllocationIsHigh) {
   const int kMinStartBps360p = 222000;
   fake_encoder_.SetResolutionBitrateLimits(
@@ -6411,13 +6453,51 @@
       DataRate::BitsPerSec(kMinStartBps360p - 1),  // stable_target_bitrate
       DataRate::BitsPerSec(kMinStartBps360p),      // link_allocation
       0, 0, 0);
+
+  const int kWidth = 640;
+  const int kHeight = 360;
+
+  const int kSmallWidth = 640 / 2;
+  const int kSmallHeight = 360 / 2;
+
+  int captureWidth;
+  int captureHeight;
+
+  if (frame_resolution_change_method_ ==
+      FrameResolutionChangeMethod::MODIFY_REQUESTED_RESOLUTION) {
+    captureWidth = kWidth;
+    captureHeight = kHeight;
+    ASSERT_THAT(video_encoder_config_.simulcast_layers, SizeIs(1));
+    video_encoder_config_.simulcast_layers[0].requested_resolution.emplace(
+        Resolution({.width = kSmallWidth, .height = kSmallHeight}));
+    video_stream_encoder_->ConfigureEncoder(video_encoder_config_.Copy(),
+                                            kMaxPayloadLength);
+  } else {
+    captureWidth = kSmallWidth;
+    captureHeight = kSmallHeight;
+  }
+
   // Frame should not be dropped, bitrate not too low for frame.
-  video_source_.IncomingCapturedFrame(CreateFrame(1, 320, 180));
+  video_source_.IncomingCapturedFrame(
+      CreateFrame(1, captureWidth, captureHeight));
   WaitForEncodedFrame(1);
 
   // Incoming resolution increases, initial frame drop activates.
+  if (frame_resolution_change_method_ ==
+      FrameResolutionChangeMethod::MODIFY_REQUESTED_RESOLUTION) {
+    ASSERT_THAT(video_encoder_config_.simulcast_layers, SizeIs(1));
+    video_encoder_config_.simulcast_layers[0].requested_resolution.emplace(
+        Resolution({.width = kWidth, .height = kHeight}));
+    video_stream_encoder_->ConfigureEncoder(video_encoder_config_.Copy(),
+                                            kMaxPayloadLength);
+  } else {
+    captureWidth = kWidth;
+    captureHeight = kHeight;
+  }
+
   // Frame should be dropped, link allocation not too low for frame.
-  video_source_.IncomingCapturedFrame(CreateFrame(2, 640, 360));
+  video_source_.IncomingCapturedFrame(
+      CreateFrame(2, captureWidth, captureHeight));
   WaitForEncodedFrame(2);
 
   video_stream_encoder_->Stop();