Introduce FrameGeneratorInterface

Introduce FrameGeneratorInterface to make FrameGenerator API available
for downstream projects.

Bug: webrtc:10138
Change-Id: I4216775e4b8b54c3f1c72d67ffbda31eb082fd7e
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/161234
Reviewed-by: Niels Moller <nisse@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Commit-Queue: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30009}
diff --git a/api/BUILD.gn b/api/BUILD.gn
index 48d3770..4265f97 100644
--- a/api/BUILD.gn
+++ b/api/BUILD.gn
@@ -374,6 +374,20 @@
   ]
 }
 
+rtc_source_set("frame_generator_api") {
+  visibility = [ "*" ]
+  testonly = true
+  sources = [
+    "test/frame_generator_interface.h",
+  ]
+
+  deps = [
+    ":scoped_refptr",
+    "video:video_frame",
+    "//third_party/abseil-cpp/absl/types:optional",
+  ]
+}
+
 rtc_library("test_dependency_factory") {
   visibility = [ "*" ]
   testonly = true
@@ -433,6 +447,21 @@
       "../test/pc/e2e:peerconnection_quality_test",
     ]
   }
+
+  rtc_library("create_frame_generator") {
+    visibility = [ "*" ]
+    testonly = true
+    sources = [
+      "test/create_frame_generator.cc",
+      "test/create_frame_generator.h",
+    ]
+    deps = [
+      ":frame_generator_api",
+      "../system_wrappers",
+      "../test:video_test_common",
+      "//third_party/abseil-cpp/absl/types:optional",
+    ]
+  }
 }
 
 rtc_source_set("libjingle_logging_api") {
diff --git a/api/test/DEPS b/api/test/DEPS
index 1fced5d..b5bbed6 100644
--- a/api/test/DEPS
+++ b/api/test/DEPS
@@ -37,4 +37,7 @@
     "+rtc_base/synchronization/yield_policy.h",
     "+system_wrappers/include/clock.h",
   ],
+  "create_frame_generator\.h": [
+    "+system_wrappers/include/clock.h",
+  ],
 }
diff --git a/api/test/create_frame_generator.cc b/api/test/create_frame_generator.cc
new file mode 100644
index 0000000..b6e62a4
--- /dev/null
+++ b/api/test/create_frame_generator.cc
@@ -0,0 +1,60 @@
+/*
+ *  Copyright (c) 2019 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/test/create_frame_generator.h"
+
+#include <utility>
+
+#include "test/frame_generator.h"
+
+namespace webrtc {
+namespace test {
+
+std::unique_ptr<FrameGeneratorInterface> CreateSquareFrameGenerator(
+    int width,
+    int height,
+    absl::optional<FrameGeneratorInterface::OutputType> type,
+    absl::optional<int> num_squares) {
+  return FrameGenerator::CreateSquareGenerator(width, height, type,
+                                               num_squares);
+}
+
+std::unique_ptr<FrameGeneratorInterface> CreateFromYuvFileFrameGenerator(
+    std::vector<std::string> files,
+    size_t width,
+    size_t height,
+    int frame_repeat_count) {
+  return FrameGenerator::CreateFromYuvFile(std::move(files), width, height,
+                                           frame_repeat_count);
+}
+
+std::unique_ptr<FrameGeneratorInterface>
+CreateScrollingInputFromYuvFilesFrameGenerator(
+    Clock* clock,
+    std::vector<std::string> filenames,
+    size_t source_width,
+    size_t source_height,
+    size_t target_width,
+    size_t target_height,
+    int64_t scroll_time_ms,
+    int64_t pause_time_ms) {
+  return FrameGenerator::CreateScrollingInputFromYuvFiles(
+      clock, std::move(filenames), source_width, source_height, target_width,
+      target_height, scroll_time_ms, pause_time_ms);
+}
+
+std::unique_ptr<FrameGeneratorInterface>
+CreateSlideFrameGenerator(int width, int height, int frame_repeat_count) {
+  return FrameGenerator::CreateSlideGenerator(width, height,
+                                              frame_repeat_count);
+}
+
+}  // namespace test
+}  // namespace webrtc
diff --git a/api/test/create_frame_generator.h b/api/test/create_frame_generator.h
new file mode 100644
index 0000000..692c964
--- /dev/null
+++ b/api/test/create_frame_generator.h
@@ -0,0 +1,72 @@
+/*
+ *  Copyright (c) 2019 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.
+ */
+
+#ifndef API_TEST_CREATE_FRAME_GENERATOR_H_
+#define API_TEST_CREATE_FRAME_GENERATOR_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/test/frame_generator_interface.h"
+#include "system_wrappers/include/clock.h"
+
+namespace webrtc {
+namespace test {
+
+// Creates a frame generator that produces frames with small squares that
+// move randomly towards the lower right corner.
+// |type| has the default value FrameGeneratorInterface::OutputType::I420.
+// |num_squares| has the default value 10.
+std::unique_ptr<FrameGeneratorInterface> CreateSquareFrameGenerator(
+    int width,
+    int height,
+    absl::optional<FrameGeneratorInterface::OutputType> type,
+    absl::optional<int> num_squares);
+
+// Creates a frame generator that repeatedly plays a set of yuv files.
+// The frame_repeat_count determines how many times each frame is shown,
+// with 1 = show each frame once, etc.
+std::unique_ptr<FrameGeneratorInterface> CreateFromYuvFileFrameGenerator(
+    std::vector<std::string> files,
+    size_t width,
+    size_t height,
+    int frame_repeat_count);
+
+// Creates a frame generator which takes a set of yuv files (wrapping a
+// frame generator created by CreateFromYuvFile() above), but outputs frames
+// that have been cropped to specified resolution: source_width/source_height
+// is the size of the source images, target_width/target_height is the size of
+// the cropped output. For each source image read, the cropped viewport will
+// be scrolled top to bottom/left to right for scroll_tim_ms milliseconds.
+// After that the image will stay in place for pause_time_ms milliseconds,
+// and then this will be repeated with the next file from the input set.
+std::unique_ptr<FrameGeneratorInterface>
+CreateScrollingInputFromYuvFilesFrameGenerator(
+    Clock* clock,
+    std::vector<std::string> filenames,
+    size_t source_width,
+    size_t source_height,
+    size_t target_width,
+    size_t target_height,
+    int64_t scroll_time_ms,
+    int64_t pause_time_ms);
+
+// Creates a frame generator that produces randomly generated slides. It fills
+// the frames with randomly sized and colored squares.
+// |frame_repeat_count| determines how many times each slide is shown.
+std::unique_ptr<FrameGeneratorInterface>
+CreateSlideFrameGenerator(int width, int height, int frame_repeat_count);
+
+}  // namespace test
+}  // namespace webrtc
+
+#endif  // API_TEST_CREATE_FRAME_GENERATOR_H_
diff --git a/api/test/frame_generator_interface.h b/api/test/frame_generator_interface.h
new file mode 100644
index 0000000..691b6ee
--- /dev/null
+++ b/api/test/frame_generator_interface.h
@@ -0,0 +1,50 @@
+/*
+ *  Copyright (c) 2019 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.
+ */
+
+#ifndef API_TEST_FRAME_GENERATOR_INTERFACE_H_
+#define API_TEST_FRAME_GENERATOR_INTERFACE_H_
+
+#include <utility>
+
+#include "absl/types/optional.h"
+#include "api/scoped_refptr.h"
+#include "api/video/video_frame.h"
+#include "api/video/video_frame_buffer.h"
+
+namespace webrtc {
+namespace test {
+
+class FrameGeneratorInterface {
+ public:
+  struct VideoFrameData {
+    VideoFrameData(rtc::scoped_refptr<VideoFrameBuffer> buffer,
+                   absl::optional<VideoFrame::UpdateRect> update_rect)
+        : buffer(std::move(buffer)), update_rect(update_rect) {}
+
+    rtc::scoped_refptr<VideoFrameBuffer> buffer;
+    absl::optional<VideoFrame::UpdateRect> update_rect;
+  };
+
+  enum class OutputType { kI420, kI420A, kI010 };
+
+  virtual ~FrameGeneratorInterface() = default;
+
+  // Returns VideoFrameBuffer and area where most of update was done to set them
+  // on the VideoFrame object.
+  virtual VideoFrameData NextFrame() = 0;
+
+  // Change the capture resolution.
+  virtual void ChangeResolution(size_t width, size_t height) = 0;
+};
+
+}  // namespace test
+}  // namespace webrtc
+
+#endif  // API_TEST_FRAME_GENERATOR_INTERFACE_H_
diff --git a/test/BUILD.gn b/test/BUILD.gn
index 8c22c92..a5519d2 100644
--- a/test/BUILD.gn
+++ b/test/BUILD.gn
@@ -53,6 +53,7 @@
 
   deps = [
     ":fileutils",
+    "../api:frame_generator_api",
     "../api:scoped_refptr",
     "../api/task_queue",
     "../api/video:video_frame",
diff --git a/test/frame_generator.h b/test/frame_generator.h
index 95b710f..47251b3 100644
--- a/test/frame_generator.h
+++ b/test/frame_generator.h
@@ -14,6 +14,7 @@
 #include <string>
 #include <vector>
 
+#include "api/test/frame_generator_interface.h"
 #include "api/video/video_frame.h"
 #include "api/video/video_source_interface.h"
 #include "rtc_base/critical_section.h"
@@ -45,31 +46,12 @@
   rtc::VideoSinkWants sink_wants_ RTC_GUARDED_BY(crit_);
 };
 
-class FrameGenerator {
+class FrameGenerator : public FrameGeneratorInterface {
  public:
-  struct VideoFrameData {
-    VideoFrameData(rtc::scoped_refptr<VideoFrameBuffer> buffer,
-                   absl::optional<VideoFrame::UpdateRect> update_rect)
-        : buffer(std::move(buffer)), update_rect(update_rect) {}
-
-    rtc::scoped_refptr<VideoFrameBuffer> buffer;
-    absl::optional<VideoFrame::UpdateRect> update_rect;
-  };
-
   virtual ~FrameGenerator() = default;
 
-  // Returns VideoFrameBuffer and area where most of update was done to set them
-  // on the VideoFrame object. Returned frames can share same buffer.
-  virtual VideoFrameData NextFrame() = 0;
-
   // Change the capture resolution.
-  virtual void ChangeResolution(size_t width, size_t height);
-
-  enum class OutputType {
-    kI420,
-    kI420A,
-    kI010
-  };
+  void ChangeResolution(size_t width, size_t height) override;
 
   // Creates a frame generator that produces frames with small squares that
   // move randomly towards the lower right corner.
diff --git a/test/frame_generator_capturer.cc b/test/frame_generator_capturer.cc
index 5f1c6e0..e817db9 100644
--- a/test/frame_generator_capturer.cc
+++ b/test/frame_generator_capturer.cc
@@ -44,7 +44,7 @@
 
 FrameGeneratorCapturer::FrameGeneratorCapturer(
     Clock* clock,
-    std::unique_ptr<FrameGenerator> frame_generator,
+    std::unique_ptr<FrameGeneratorInterface> frame_generator,
     int target_fps,
     TaskQueueFactory& task_queue_factory)
     : clock_(clock),
diff --git a/test/frame_generator_capturer.h b/test/frame_generator_capturer.h
index faf0498..6220870 100644
--- a/test/frame_generator_capturer.h
+++ b/test/frame_generator_capturer.h
@@ -96,10 +96,11 @@
     virtual ~SinkWantsObserver() {}
   };
 
-  FrameGeneratorCapturer(Clock* clock,
-                         std::unique_ptr<FrameGenerator> frame_generator,
-                         int target_fps,
-                         TaskQueueFactory& task_queue_factory);
+  FrameGeneratorCapturer(
+      Clock* clock,
+      std::unique_ptr<FrameGeneratorInterface> frame_generator,
+      int target_fps,
+      TaskQueueFactory& task_queue_factory);
   virtual ~FrameGeneratorCapturer();
 
   static std::unique_ptr<FrameGeneratorCapturer> Create(
@@ -154,7 +155,7 @@
   SinkWantsObserver* sink_wants_observer_ RTC_GUARDED_BY(&lock_);
 
   rtc::CriticalSection lock_;
-  std::unique_ptr<FrameGenerator> frame_generator_;
+  std::unique_ptr<FrameGeneratorInterface> frame_generator_;
 
   int source_fps_ RTC_GUARDED_BY(&lock_);
   int target_capture_fps_ RTC_GUARDED_BY(&lock_);
diff --git a/test/pc/e2e/BUILD.gn b/test/pc/e2e/BUILD.gn
index ae6bc74..9263014 100644
--- a/test/pc/e2e/BUILD.gn
+++ b/test/pc/e2e/BUILD.gn
@@ -292,6 +292,8 @@
       "../..:platform_video_capturer",
       "../..:video_test_common",
       "../../../api:audio_quality_analyzer_api",
+      "../../../api:create_frame_generator",
+      "../../../api:frame_generator_api",
       "../../../api:libjingle_peerconnection_api",
       "../../../api:media_stream_interface",
       "../../../api:peer_connection_quality_test_fixture_api",
diff --git a/test/pc/e2e/peer_connection_quality_test.cc b/test/pc/e2e/peer_connection_quality_test.cc
index a5fa65a..9baa3de 100644
--- a/test/pc/e2e/peer_connection_quality_test.cc
+++ b/test/pc/e2e/peer_connection_quality_test.cc
@@ -21,6 +21,7 @@
 #include "api/rtc_event_log_output_file.h"
 #include "api/scoped_refptr.h"
 #include "api/task_queue/default_task_queue_factory.h"
+#include "api/test/create_frame_generator.h"
 #include "api/test/video_quality_analyzer_interface.h"
 #include "api/units/time_delta.h"
 #include "api/video/video_source_interface.h"
@@ -791,24 +792,24 @@
     return capturer;
   }
 
-  std::unique_ptr<test::FrameGenerator> frame_generator = nullptr;
+  std::unique_ptr<test::FrameGeneratorInterface> frame_generator = nullptr;
   if (video_config.generator) {
-    absl::optional<test::FrameGenerator::OutputType> frame_generator_type =
-        absl::nullopt;
+    absl::optional<test::FrameGeneratorInterface::OutputType>
+        frame_generator_type = absl::nullopt;
     if (video_config.generator == VideoGeneratorType::kDefault) {
-      frame_generator_type = test::FrameGenerator::OutputType::kI420;
+      frame_generator_type = test::FrameGeneratorInterface::OutputType::kI420;
     } else if (video_config.generator == VideoGeneratorType::kI420A) {
-      frame_generator_type = test::FrameGenerator::OutputType::kI420A;
+      frame_generator_type = test::FrameGeneratorInterface::OutputType::kI420A;
     } else if (video_config.generator == VideoGeneratorType::kI010) {
-      frame_generator_type = test::FrameGenerator::OutputType::kI010;
+      frame_generator_type = test::FrameGeneratorInterface::OutputType::kI010;
     }
-    frame_generator = test::FrameGenerator::CreateSquareGenerator(
-        static_cast<int>(video_config.width),
-        static_cast<int>(video_config.height), frame_generator_type,
-        absl::nullopt);
+    frame_generator =
+        test::CreateSquareFrameGenerator(static_cast<int>(video_config.width),
+                                         static_cast<int>(video_config.height),
+                                         frame_generator_type, absl::nullopt);
   }
   if (video_config.input_file_name) {
-    frame_generator = test::FrameGenerator::CreateFromYuvFile(
+    frame_generator = test::CreateFromYuvFileFrameGenerator(
         std::vector<std::string>(/*count=*/1,
                                  video_config.input_file_name.value()),
         video_config.width, video_config.height, /*frame_repeat_count=*/1);
@@ -826,12 +827,12 @@
   return capturer;
 }
 
-std::unique_ptr<test::FrameGenerator>
+std::unique_ptr<test::FrameGeneratorInterface>
 PeerConnectionE2EQualityTest::CreateScreenShareFrameGenerator(
     const VideoConfig& video_config) {
   RTC_CHECK(video_config.screen_share_config);
   if (video_config.screen_share_config->generate_slides) {
-    return test::FrameGenerator::CreateSlideGenerator(
+    return test::CreateSlideFrameGenerator(
         video_config.width, video_config.height,
         video_config.screen_share_config->slide_change_interval.seconds() *
             video_config.fps);
@@ -849,7 +850,7 @@
   }
   if (!video_config.screen_share_config->scrolling_params) {
     // Cycle image every slide_change_interval seconds.
-    return test::FrameGenerator::CreateFromYuvFile(
+    return test::CreateFromYuvFileFrameGenerator(
         slides, video_config.width, video_config.height,
         video_config.screen_share_config->slide_change_interval.seconds() *
             video_config.fps);
@@ -860,7 +861,7 @@
       video_config.screen_share_config->slide_change_interval -
       video_config.screen_share_config->scrolling_params->duration;
 
-  return test::FrameGenerator::CreateScrollingInputFromYuvFiles(
+  return test::CreateScrollingInputFromYuvFilesFrameGenerator(
       clock_, slides,
       video_config.screen_share_config->scrolling_params->source_width,
       video_config.screen_share_config->scrolling_params->source_height,
diff --git a/test/pc/e2e/peer_connection_quality_test.h b/test/pc/e2e/peer_connection_quality_test.h
index 669cdb3..aeff087 100644
--- a/test/pc/e2e/peer_connection_quality_test.h
+++ b/test/pc/e2e/peer_connection_quality_test.h
@@ -17,6 +17,7 @@
 
 #include "api/task_queue/task_queue_factory.h"
 #include "api/test/audio_quality_analyzer_interface.h"
+#include "api/test/frame_generator_interface.h"
 #include "api/test/peerconnection_quality_test_fixture.h"
 #include "api/units/time_delta.h"
 #include "api/units/timestamp.h"
@@ -289,8 +290,8 @@
       std::unique_ptr<rtc::VideoSourceInterface<VideoFrame>> source,
       std::unique_ptr<test::TestVideoCapturer::FramePreprocessor>
           frame_preprocessor);
-  std::unique_ptr<test::FrameGenerator> CreateScreenShareFrameGenerator(
-      const VideoConfig& video_config);
+  std::unique_ptr<test::FrameGeneratorInterface>
+  CreateScreenShareFrameGenerator(const VideoConfig& video_config);
   void MaybeAddAudio(TestPeer* peer);
   void SetPeerCodecPreferences(TestPeer* peer, const RunParams& run_params);
   void SetupCall(const RunParams& run_params);