FrameGeneratorCapturer: add methods OnOutputFormatRequest and GetResolution

To be used in tests.

Bug: none
Change-Id: Ia7b551b3ac66ed23d1907df56ddc4e09e3667a2b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/245644
Reviewed-by: Artem Titov <titovartem@webrtc.org>
Commit-Queue: Åsa Persson <asapersson@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#35703}
diff --git a/test/frame_generator_capturer.cc b/test/frame_generator_capturer.cc
index a4c528e..1a51bfc 100644
--- a/test/frame_generator_capturer.cc
+++ b/test/frame_generator_capturer.cc
@@ -175,31 +175,49 @@
 }
 
 void FrameGeneratorCapturer::InsertFrame() {
-  MutexLock lock(&lock_);
-  if (sending_) {
-    FrameGeneratorInterface::VideoFrameData frame_data =
-        frame_generator_->NextFrame();
-    // TODO(srte): Use more advanced frame rate control to allow arbritrary
-    // fractions.
-    int decimation =
-        std::round(static_cast<double>(source_fps_) / target_capture_fps_);
-    for (int i = 1; i < decimation; ++i)
-      frame_data = frame_generator_->NextFrame();
+  absl::optional<Resolution> resolution;
 
-    VideoFrame frame = VideoFrame::Builder()
-                           .set_video_frame_buffer(frame_data.buffer)
-                           .set_rotation(fake_rotation_)
-                           .set_timestamp_us(clock_->TimeInMicroseconds())
-                           .set_ntp_time_ms(clock_->CurrentNtpInMilliseconds())
-                           .set_update_rect(frame_data.update_rect)
-                           .set_color_space(fake_color_space_)
-                           .build();
-    if (first_frame_capture_time_ == -1) {
-      first_frame_capture_time_ = frame.ntp_time_ms();
+  {
+    MutexLock lock(&lock_);
+    if (sending_) {
+      FrameGeneratorInterface::VideoFrameData frame_data =
+          frame_generator_->NextFrame();
+      // TODO(srte): Use more advanced frame rate control to allow arbritrary
+      // fractions.
+      int decimation =
+          std::round(static_cast<double>(source_fps_) / target_capture_fps_);
+      for (int i = 1; i < decimation; ++i)
+        frame_data = frame_generator_->NextFrame();
+
+      VideoFrame frame =
+          VideoFrame::Builder()
+              .set_video_frame_buffer(frame_data.buffer)
+              .set_rotation(fake_rotation_)
+              .set_timestamp_us(clock_->TimeInMicroseconds())
+              .set_ntp_time_ms(clock_->CurrentNtpInMilliseconds())
+              .set_update_rect(frame_data.update_rect)
+              .set_color_space(fake_color_space_)
+              .build();
+      if (first_frame_capture_time_ == -1) {
+        first_frame_capture_time_ = frame.ntp_time_ms();
+      }
+
+      resolution = Resolution{frame.width(), frame.height()};
+
+      TestVideoCapturer::OnFrame(frame);
     }
-
-    TestVideoCapturer::OnFrame(frame);
   }
+
+  if (resolution) {
+    MutexLock lock(&stats_lock_);
+    source_resolution_ = resolution;
+  }
+}
+
+absl::optional<FrameGeneratorCapturer::Resolution>
+FrameGeneratorCapturer::GetResolution() {
+  MutexLock lock(&stats_lock_);
+  return source_resolution_;
 }
 
 void FrameGeneratorCapturer::Start() {
@@ -243,6 +261,13 @@
   target_capture_fps_ = std::min(source_fps_, target_framerate);
 }
 
+void FrameGeneratorCapturer::OnOutputFormatRequest(
+    int width,
+    int height,
+    const absl::optional<int>& max_fps) {
+  TestVideoCapturer::OnOutputFormatRequest(width, height, max_fps);
+}
+
 void FrameGeneratorCapturer::SetSinkWantsObserver(SinkWantsObserver* observer) {
   MutexLock lock(&lock_);
   RTC_DCHECK(!sink_wants_observer_);
diff --git a/test/frame_generator_capturer.h b/test/frame_generator_capturer.h
index 1e915fc..e310e40 100644
--- a/test/frame_generator_capturer.h
+++ b/test/frame_generator_capturer.h
@@ -132,6 +132,16 @@
   void ChangeResolution(size_t width, size_t height);
   void ChangeFramerate(int target_framerate);
 
+  struct Resolution {
+    int width;
+    int height;
+  };
+  absl::optional<Resolution> GetResolution();
+
+  void OnOutputFormatRequest(int width,
+                             int height,
+                             const absl::optional<int>& max_fps);
+
   void SetSinkWantsObserver(SinkWantsObserver* observer);
 
   void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
@@ -167,6 +177,10 @@
   absl::optional<ColorSpace> fake_color_space_ RTC_GUARDED_BY(&lock_);
 
   int64_t first_frame_capture_time_;
+
+  Mutex stats_lock_;
+  absl::optional<Resolution> source_resolution_ RTC_GUARDED_BY(&stats_lock_);
+
   // Must be the last field, so it will be deconstructed first as tasks
   // in the TaskQueue access other fields of the instance of this class.
   rtc::TaskQueue task_queue_;
diff --git a/test/frame_generator_capturer_unittest.cc b/test/frame_generator_capturer_unittest.cc
index a76cb95..d8371f4 100644
--- a/test/frame_generator_capturer_unittest.cc
+++ b/test/frame_generator_capturer_unittest.cc
@@ -19,6 +19,9 @@
 using ::testing::Eq;
 using ::testing::Property;
 
+constexpr int kWidth = 640;
+constexpr int kHeight = 360;
+
 class MockVideoSinkInterfaceVideoFrame
     : public rtc::VideoSinkInterface<VideoFrame> {
  public:
@@ -26,6 +29,7 @@
   MOCK_METHOD(void, OnDiscardedFrame, (), (override));
 };
 }  // namespace
+
 TEST(FrameGeneratorCapturerTest, CreateFromConfig) {
   GlobalSimulatedTimeController time(Timestamp::Seconds(1000));
   FrameGeneratorCapturerConfig config;
@@ -41,5 +45,45 @@
       .Times(21);
   time.AdvanceTime(TimeDelta::Seconds(1));
 }
+
+TEST(FrameGeneratorCapturerTest, OnOutputFormatRequest) {
+  GlobalSimulatedTimeController time(Timestamp::Seconds(1000));
+  FrameGeneratorCapturerConfig config;
+  config.squares_video->width = kWidth;
+  config.squares_video->height = kHeight;
+  config.squares_video->framerate = 20;
+  auto capturer = FrameGeneratorCapturer::Create(
+      time.GetClock(), *time.GetTaskQueueFactory(), config);
+  testing::StrictMock<MockVideoSinkInterfaceVideoFrame> mock_sink;
+  capturer->AddOrUpdateSink(&mock_sink, rtc::VideoSinkWants());
+  capturer->OnOutputFormatRequest(kWidth / 2, kHeight / 2, /*max_fps=*/10);
+  capturer->Start();
+  EXPECT_CALL(mock_sink, OnFrame(Property(&VideoFrame::width, Eq(kWidth / 2))))
+      .Times(11);
+  time.AdvanceTime(TimeDelta::Seconds(1));
+}
+
+TEST(FrameGeneratorCapturerTest, ChangeResolution) {
+  GlobalSimulatedTimeController time(Timestamp::Seconds(1000));
+  FrameGeneratorCapturerConfig config;
+  config.squares_video->width = kWidth;
+  config.squares_video->height = kHeight;
+  config.squares_video->framerate = 20;
+  auto capturer = FrameGeneratorCapturer::Create(
+      time.GetClock(), *time.GetTaskQueueFactory(), config);
+  EXPECT_FALSE(capturer->GetResolution());
+  capturer->Start();
+  time.AdvanceTime(TimeDelta::Seconds(1));
+  ASSERT_TRUE(capturer->GetResolution());
+  EXPECT_EQ(kWidth, capturer->GetResolution()->width);
+  EXPECT_EQ(kHeight, capturer->GetResolution()->height);
+
+  capturer->ChangeResolution(kWidth / 2, kHeight / 2);
+  time.AdvanceTime(TimeDelta::Seconds(1));
+  ASSERT_TRUE(capturer->GetResolution());
+  EXPECT_EQ(kWidth / 2, capturer->GetResolution()->width);
+  EXPECT_EQ(kHeight / 2, capturer->GetResolution()->height);
+}
+
 }  // namespace test
 }  // namespace webrtc
diff --git a/test/test_video_capturer.cc b/test/test_video_capturer.cc
index 9ce4aa0..4a4adc6 100644
--- a/test/test_video_capturer.cc
+++ b/test/test_video_capturer.cc
@@ -21,6 +21,17 @@
 namespace test {
 TestVideoCapturer::~TestVideoCapturer() = default;
 
+void TestVideoCapturer::OnOutputFormatRequest(
+    int width,
+    int height,
+    const absl::optional<int>& max_fps) {
+  absl::optional<std::pair<int, int>> target_aspect_ratio =
+      std::make_pair(width, height);
+  absl::optional<int> max_pixel_count = width * height;
+  video_adapter_.OnOutputFormatRequest(target_aspect_ratio, max_pixel_count,
+                                       max_fps);
+}
+
 void TestVideoCapturer::OnFrame(const VideoFrame& original_frame) {
   int cropped_width = 0;
   int cropped_height = 0;
diff --git a/test/test_video_capturer.h b/test/test_video_capturer.h
index dff529c..6fafd96 100644
--- a/test/test_video_capturer.h
+++ b/test/test_video_capturer.h
@@ -41,6 +41,9 @@
     MutexLock lock(&lock_);
     preprocessor_ = std::move(preprocessor);
   }
+  void OnOutputFormatRequest(int width,
+                             int height,
+                             const absl::optional<int>& max_fps);
 
  protected:
   void OnFrame(const VideoFrame& frame);