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_H_
11 #define TEST_FRAME_GENERATOR_H_
12 
13 #include <memory>
14 #include <string>
15 #include <vector>
16 
17 #include "api/scoped_refptr.h"
18 #include "api/test/frame_generator_interface.h"
19 #include "api/video/i420_buffer.h"
20 #include "api/video/video_frame.h"
21 #include "api/video/video_frame_buffer.h"
22 #include "api/video/video_source_interface.h"
23 #include "rtc_base/random.h"
24 #include "rtc_base/synchronization/mutex.h"
25 #include "system_wrappers/include/clock.h"
26 
27 namespace webrtc {
28 namespace test {
29 
30 // SquareGenerator is a FrameGenerator that draws a given amount of randomly
31 // sized and colored squares. Between each new generated frame, the squares
32 // are moved slightly towards the lower right corner.
33 class SquareGenerator : public FrameGeneratorInterface {
34  public:
35   SquareGenerator(int width, int height, OutputType type, int num_squares);
36 
37   void ChangeResolution(size_t width, size_t height) override;
38   VideoFrameData NextFrame() override;
39 
40  private:
41   rtc::scoped_refptr<I420Buffer> CreateI420Buffer(int width, int height);
42 
43   class Square {
44    public:
45     Square(int width, int height, int seed);
46 
47     void Draw(const rtc::scoped_refptr<VideoFrameBuffer>& frame_buffer);
48 
49    private:
50     Random random_generator_;
51     int x_;
52     int y_;
53     const int length_;
54     const uint8_t yuv_y_;
55     const uint8_t yuv_u_;
56     const uint8_t yuv_v_;
57     const uint8_t yuv_a_;
58   };
59 
60   Mutex mutex_;
61   const OutputType type_;
62   int width_ RTC_GUARDED_BY(&mutex_);
63   int height_ RTC_GUARDED_BY(&mutex_);
64   std::vector<std::unique_ptr<Square>> squares_ RTC_GUARDED_BY(&mutex_);
65 };
66 
67 class YuvFileGenerator : public FrameGeneratorInterface {
68  public:
69   YuvFileGenerator(std::vector<FILE*> files,
70                    size_t width,
71                    size_t height,
72                    int frame_repeat_count);
73 
74   ~YuvFileGenerator();
75 
76   VideoFrameData NextFrame() override;
ChangeResolution(size_t width,size_t height)77   void ChangeResolution(size_t width, size_t height) override {
78     RTC_NOTREACHED();
79   }
80 
81  private:
82   // Returns true if the new frame was loaded.
83   // False only in case of a single file with a single frame in it.
84   bool ReadNextFrame();
85 
86   size_t file_index_;
87   size_t frame_index_;
88   const std::vector<FILE*> files_;
89   const size_t width_;
90   const size_t height_;
91   const size_t frame_size_;
92   const std::unique_ptr<uint8_t[]> frame_buffer_;
93   const int frame_display_count_;
94   int current_display_count_;
95   rtc::scoped_refptr<I420Buffer> last_read_buffer_;
96 };
97 
98 // SlideGenerator works similarly to YuvFileGenerator but it fills the frames
99 // with randomly sized and colored squares instead of reading their content
100 // from files.
101 class SlideGenerator : public FrameGeneratorInterface {
102  public:
103   SlideGenerator(int width, int height, int frame_repeat_count);
104 
105   VideoFrameData NextFrame() override;
ChangeResolution(size_t width,size_t height)106   void ChangeResolution(size_t width, size_t height) override {
107     RTC_NOTREACHED();
108   }
109 
110  private:
111   // Generates some randomly sized and colored squares scattered
112   // over the frame.
113   void GenerateNewFrame();
114 
115   const int width_;
116   const int height_;
117   const int frame_display_count_;
118   int current_display_count_;
119   Random random_generator_;
120   rtc::scoped_refptr<I420Buffer> buffer_;
121 };
122 
123 class ScrollingImageFrameGenerator : public FrameGeneratorInterface {
124  public:
125   ScrollingImageFrameGenerator(Clock* clock,
126                                const std::vector<FILE*>& files,
127                                size_t source_width,
128                                size_t source_height,
129                                size_t target_width,
130                                size_t target_height,
131                                int64_t scroll_time_ms,
132                                int64_t pause_time_ms);
133   ~ScrollingImageFrameGenerator() override = default;
134 
135   VideoFrameData NextFrame() override;
ChangeResolution(size_t width,size_t height)136   void ChangeResolution(size_t width, size_t height) override {
137     RTC_NOTREACHED();
138   }
139 
140  private:
141   void UpdateSourceFrame(size_t frame_num);
142   void CropSourceToScrolledImage(double scroll_factor);
143 
144   Clock* const clock_;
145   const int64_t start_time_;
146   const int64_t scroll_time_;
147   const int64_t pause_time_;
148   const size_t num_frames_;
149   const int target_width_;
150   const int target_height_;
151 
152   size_t current_frame_num_;
153   bool prev_frame_not_scrolled_;
154   VideoFrameData current_source_frame_;
155   VideoFrameData current_frame_;
156   YuvFileGenerator file_generator_;
157 };
158 
159 }  // namespace test
160 }  // namespace webrtc
161 
162 #endif  // TEST_FRAME_GENERATOR_H_
163