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