1 /*
2  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 #ifndef TEST_FRAME_GENERATOR_CAPTURER_H_
11 #define TEST_FRAME_GENERATOR_CAPTURER_H_
12 
13 #include <memory>
14 #include <string>
15 
16 #include "api/task_queue/task_queue_factory.h"
17 #include "api/test/frame_generator_interface.h"
18 #include "api/video/video_frame.h"
19 #include "rtc_base/synchronization/mutex.h"
20 #include "rtc_base/task_queue.h"
21 #include "rtc_base/task_utils/repeating_task.h"
22 #include "system_wrappers/include/clock.h"
23 #include "test/test_video_capturer.h"
24 
25 namespace webrtc {
26 
27 namespace test {
28 namespace frame_gen_cap_impl {
29 template <typename T>
30 class AutoOpt : public absl::optional<T> {
31  public:
32   using absl::optional<T>::optional;
33   T* operator->() {
34     if (!absl::optional<T>::has_value())
35       this->emplace(T());
36     return absl::optional<T>::operator->();
37   }
38 };
39 }  // namespace frame_gen_cap_impl
40 struct FrameGeneratorCapturerConfig {
41   struct SquaresVideo {
42     int framerate = 30;
43     FrameGeneratorInterface::OutputType pixel_format =
44         FrameGeneratorInterface::OutputType::kI420;
45     int width = 320;
46     int height = 180;
47     int num_squares = 10;
48   };
49 
50   struct SquareSlides {
51     int framerate = 30;
52     TimeDelta change_interval = TimeDelta::Seconds(10);
53     int width = 1600;
54     int height = 1200;
55   };
56 
57   struct VideoFile {
58     int framerate = 30;
59     std::string name;
60     // Must be set to width and height of the source video file.
61     int width = 0;
62     int height = 0;
63   };
64 
65   struct ImageSlides {
66     int framerate = 30;
67     TimeDelta change_interval = TimeDelta::Seconds(10);
68     struct Crop {
69       TimeDelta scroll_duration = TimeDelta::Seconds(0);
70       absl::optional<int> width;
71       absl::optional<int> height;
72     } crop;
73     int width = 1850;
74     int height = 1110;
75     std::vector<std::string> paths = {
76         "web_screenshot_1850_1110",
77         "presentation_1850_1110",
78         "photo_1850_1110",
79         "difficult_photo_1850_1110",
80     };
81   };
82 
83   frame_gen_cap_impl::AutoOpt<SquaresVideo> squares_video;
84   frame_gen_cap_impl::AutoOpt<SquareSlides> squares_slides;
85   frame_gen_cap_impl::AutoOpt<VideoFile> video_file;
86   frame_gen_cap_impl::AutoOpt<ImageSlides> image_slides;
87 };
88 
89 class FrameGeneratorCapturer : public TestVideoCapturer {
90  public:
91   class SinkWantsObserver {
92    public:
93     // OnSinkWantsChanged is called when FrameGeneratorCapturer::AddOrUpdateSink
94     // is called.
95     virtual void OnSinkWantsChanged(rtc::VideoSinkInterface<VideoFrame>* sink,
96                                     const rtc::VideoSinkWants& wants) = 0;
97 
98    protected:
~SinkWantsObserver()99     virtual ~SinkWantsObserver() {}
100   };
101 
102   FrameGeneratorCapturer(
103       Clock* clock,
104       std::unique_ptr<FrameGeneratorInterface> frame_generator,
105       int target_fps,
106       TaskQueueFactory& task_queue_factory);
107   virtual ~FrameGeneratorCapturer();
108 
109   static std::unique_ptr<FrameGeneratorCapturer> Create(
110       Clock* clock,
111       TaskQueueFactory& task_queue_factory,
112       FrameGeneratorCapturerConfig::SquaresVideo config);
113   static std::unique_ptr<FrameGeneratorCapturer> Create(
114       Clock* clock,
115       TaskQueueFactory& task_queue_factory,
116       FrameGeneratorCapturerConfig::SquareSlides config);
117   static std::unique_ptr<FrameGeneratorCapturer> Create(
118       Clock* clock,
119       TaskQueueFactory& task_queue_factory,
120       FrameGeneratorCapturerConfig::VideoFile config);
121   static std::unique_ptr<FrameGeneratorCapturer> Create(
122       Clock* clock,
123       TaskQueueFactory& task_queue_factory,
124       FrameGeneratorCapturerConfig::ImageSlides config);
125   static std::unique_ptr<FrameGeneratorCapturer> Create(
126       Clock* clock,
127       TaskQueueFactory& task_queue_factory,
128       const FrameGeneratorCapturerConfig& config);
129 
130   void Start();
131   void Stop();
132   void ChangeResolution(size_t width, size_t height);
133   void ChangeFramerate(int target_framerate);
134 
135   void SetSinkWantsObserver(SinkWantsObserver* observer);
136 
137   void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
138                        const rtc::VideoSinkWants& wants) override;
139   void RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) override;
140 
141   void ForceFrame();
142   void SetFakeRotation(VideoRotation rotation);
143   void SetFakeColorSpace(absl::optional<ColorSpace> color_space);
144 
first_frame_capture_time()145   int64_t first_frame_capture_time() const { return first_frame_capture_time_; }
146 
147   bool Init();
148 
149  private:
150   void InsertFrame();
151   static bool Run(void* obj);
152   int GetCurrentConfiguredFramerate();
153   void UpdateFps(int max_fps) RTC_EXCLUSIVE_LOCKS_REQUIRED(&lock_);
154 
155   Clock* const clock_;
156   RepeatingTaskHandle frame_task_;
157   bool sending_;
158   SinkWantsObserver* sink_wants_observer_ RTC_GUARDED_BY(&lock_);
159 
160   Mutex lock_;
161   std::unique_ptr<FrameGeneratorInterface> frame_generator_;
162 
163   int source_fps_ RTC_GUARDED_BY(&lock_);
164   int target_capture_fps_ RTC_GUARDED_BY(&lock_);
165   absl::optional<int> wanted_fps_ RTC_GUARDED_BY(&lock_);
166   VideoRotation fake_rotation_ = kVideoRotation_0;
167   absl::optional<ColorSpace> fake_color_space_ RTC_GUARDED_BY(&lock_);
168 
169   int64_t first_frame_capture_time_;
170   // Must be the last field, so it will be deconstructed first as tasks
171   // in the TaskQueue access other fields of the instance of this class.
172   rtc::TaskQueue task_queue_;
173 };
174 }  // namespace test
175 }  // namespace webrtc
176 
177 #endif  // TEST_FRAME_GENERATOR_CAPTURER_H_
178