1 /*
2  *  Copyright (c) 2004 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 
11 #ifndef MEDIA_BASE_FAKEVIDEOCAPTURER_H_
12 #define MEDIA_BASE_FAKEVIDEOCAPTURER_H_
13 
14 #include <string.h>
15 
16 #include <memory>
17 #include <vector>
18 
19 #include "api/video/i420_buffer.h"
20 #include "api/video/video_frame.h"
21 #include "media/base/videocapturer.h"
22 #include "media/base/videocommon.h"
23 #include "rtc_base/timeutils.h"
24 
25 namespace cricket {
26 
27 // Fake video capturer that allows the test to manually pump in frames.
28 class FakeVideoCapturer : public cricket::VideoCapturer {
29  public:
FakeVideoCapturer(bool is_screencast)30   explicit FakeVideoCapturer(bool is_screencast)
31       : running_(false),
32         initial_timestamp_(rtc::TimeNanos()),
33         next_timestamp_(rtc::kNumNanosecsPerMillisec),
34         is_screencast_(is_screencast),
35         rotation_(webrtc::kVideoRotation_0) {
36     // Default supported formats. Use ResetSupportedFormats to over write.
37     std::vector<cricket::VideoFormat> formats;
38     formats.push_back(cricket::VideoFormat(1280, 720,
39         cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
40     formats.push_back(cricket::VideoFormat(640, 480,
41         cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
42     formats.push_back(cricket::VideoFormat(320, 240,
43         cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
44     formats.push_back(cricket::VideoFormat(160, 120,
45         cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
46     formats.push_back(cricket::VideoFormat(1280, 720,
47         cricket::VideoFormat::FpsToInterval(60), cricket::FOURCC_I420));
48     ResetSupportedFormats(formats);
49   }
FakeVideoCapturer()50   FakeVideoCapturer() : FakeVideoCapturer(false) {}
51 
~FakeVideoCapturer()52   ~FakeVideoCapturer() {
53     SignalDestroyed(this);
54   }
55 
ResetSupportedFormats(const std::vector<cricket::VideoFormat> & formats)56   void ResetSupportedFormats(const std::vector<cricket::VideoFormat>& formats) {
57     SetSupportedFormats(formats);
58   }
CaptureFrame()59   bool CaptureFrame() {
60     if (!GetCaptureFormat()) {
61       return false;
62     }
63     return CaptureCustomFrame(GetCaptureFormat()->width,
64                               GetCaptureFormat()->height,
65                               GetCaptureFormat()->interval,
66                               GetCaptureFormat()->fourcc);
67   }
CaptureCustomFrame(int width,int height,uint32_t fourcc)68   bool CaptureCustomFrame(int width, int height, uint32_t fourcc) {
69     // Default to 30fps.
70     return CaptureCustomFrame(width, height, rtc::kNumNanosecsPerSec / 30,
71                               fourcc);
72   }
CaptureCustomFrame(int width,int height,int64_t timestamp_interval,uint32_t fourcc)73   bool CaptureCustomFrame(int width,
74                           int height,
75                           int64_t timestamp_interval,
76                           uint32_t fourcc) {
77     if (!running_) {
78       return false;
79     }
80     RTC_CHECK(fourcc == FOURCC_I420);
81     RTC_CHECK(width > 0);
82     RTC_CHECK(height > 0);
83 
84     int adapted_width;
85     int adapted_height;
86     int crop_width;
87     int crop_height;
88     int crop_x;
89     int crop_y;
90 
91     // TODO(nisse): It's a bit silly to have this logic in a fake
92     // class. Child classes of VideoCapturer are expected to call
93     // AdaptFrame, and the test case
94     // VideoCapturerTest.SinkWantsMaxPixelAndMaxPixelCountStepUp
95     // depends on this.
96     if (AdaptFrame(width, height,
97                    next_timestamp_ / rtc::kNumNanosecsPerMicrosec,
98                    next_timestamp_ / rtc::kNumNanosecsPerMicrosec,
99                    &adapted_width, &adapted_height, &crop_width, &crop_height,
100                    &crop_x, &crop_y, nullptr)) {
101       rtc::scoped_refptr<webrtc::I420Buffer> buffer(
102           webrtc::I420Buffer::Create(adapted_width, adapted_height));
103       buffer->InitializeData();
104 
105       OnFrame(webrtc::VideoFrame(
106                   buffer, rotation_,
107                   next_timestamp_ / rtc::kNumNanosecsPerMicrosec),
108               width, height);
109     }
110     next_timestamp_ += timestamp_interval;
111 
112     return true;
113   }
114 
115   sigslot::signal1<FakeVideoCapturer*> SignalDestroyed;
116 
Start(const cricket::VideoFormat & format)117   cricket::CaptureState Start(const cricket::VideoFormat& format) override {
118     SetCaptureFormat(&format);
119     running_ = true;
120     SetCaptureState(cricket::CS_RUNNING);
121     return cricket::CS_RUNNING;
122   }
Stop()123   void Stop() override {
124     running_ = false;
125     SetCaptureFormat(NULL);
126     SetCaptureState(cricket::CS_STOPPED);
127   }
IsRunning()128   bool IsRunning() override { return running_; }
IsScreencast()129   bool IsScreencast() const override { return is_screencast_; }
GetPreferredFourccs(std::vector<uint32_t> * fourccs)130   bool GetPreferredFourccs(std::vector<uint32_t>* fourccs) override {
131     fourccs->push_back(cricket::FOURCC_I420);
132     fourccs->push_back(cricket::FOURCC_MJPG);
133     return true;
134   }
135 
SetRotation(webrtc::VideoRotation rotation)136   void SetRotation(webrtc::VideoRotation rotation) {
137     rotation_ = rotation;
138   }
139 
GetRotation()140   webrtc::VideoRotation GetRotation() { return rotation_; }
141 
142  private:
143   bool running_;
144   int64_t initial_timestamp_;
145   int64_t next_timestamp_;
146   const bool is_screencast_;
147   webrtc::VideoRotation rotation_;
148 };
149 
150 }  // namespace cricket
151 
152 #endif  // MEDIA_BASE_FAKEVIDEOCAPTURER_H_
153