1 /*
2  *  Copyright (c) 2017 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 #include "modules/desktop_capture/blank_detector_desktop_capturer_wrapper.h"
12 
13 #include <memory>
14 #include <utility>
15 
16 #include "modules/desktop_capture/desktop_capturer.h"
17 #include "modules/desktop_capture/desktop_frame.h"
18 #include "modules/desktop_capture/desktop_frame_generator.h"
19 #include "modules/desktop_capture/desktop_geometry.h"
20 #include "modules/desktop_capture/desktop_region.h"
21 #include "modules/desktop_capture/fake_desktop_capturer.h"
22 #include "test/gtest.h"
23 
24 namespace webrtc {
25 
26 class BlankDetectorDesktopCapturerWrapperTest
27     : public ::testing::Test,
28       public DesktopCapturer::Callback {
29  public:
30   BlankDetectorDesktopCapturerWrapperTest();
31   ~BlankDetectorDesktopCapturerWrapperTest() override;
32 
33  protected:
34   void PerfTest(DesktopCapturer* capturer);
35 
36   const int frame_width_ = 1024;
37   const int frame_height_ = 768;
38   std::unique_ptr<BlankDetectorDesktopCapturerWrapper> wrapper_;
39   DesktopCapturer* capturer_ = nullptr;
40   BlackWhiteDesktopFramePainter painter_;
41   int num_frames_captured_ = 0;
42   DesktopCapturer::Result last_result_ = DesktopCapturer::Result::SUCCESS;
43   std::unique_ptr<DesktopFrame> last_frame_;
44 
45  private:
46   // DesktopCapturer::Callback interface.
47   void OnCaptureResult(DesktopCapturer::Result result,
48                        std::unique_ptr<DesktopFrame> frame) override;
49 
50   PainterDesktopFrameGenerator frame_generator_;
51 };
52 
53 BlankDetectorDesktopCapturerWrapperTest::
BlankDetectorDesktopCapturerWrapperTest()54     BlankDetectorDesktopCapturerWrapperTest() {
55   frame_generator_.size()->set(frame_width_, frame_height_);
56   frame_generator_.set_desktop_frame_painter(&painter_);
57   std::unique_ptr<DesktopCapturer> capturer(new FakeDesktopCapturer());
58   FakeDesktopCapturer* fake_capturer =
59       static_cast<FakeDesktopCapturer*>(capturer.get());
60   fake_capturer->set_frame_generator(&frame_generator_);
61   capturer_ = fake_capturer;
62   wrapper_.reset(new BlankDetectorDesktopCapturerWrapper(
63       std::move(capturer), RgbaColor(0, 0, 0, 0)));
64   wrapper_->Start(this);
65 }
66 
67 BlankDetectorDesktopCapturerWrapperTest::
68     ~BlankDetectorDesktopCapturerWrapperTest() = default;
69 
OnCaptureResult(DesktopCapturer::Result result,std::unique_ptr<DesktopFrame> frame)70 void BlankDetectorDesktopCapturerWrapperTest::OnCaptureResult(
71     DesktopCapturer::Result result,
72     std::unique_ptr<DesktopFrame> frame) {
73   last_result_ = result;
74   last_frame_ = std::move(frame);
75   num_frames_captured_++;
76 }
77 
PerfTest(DesktopCapturer * capturer)78 void BlankDetectorDesktopCapturerWrapperTest::PerfTest(
79     DesktopCapturer* capturer) {
80   for (int i = 0; i < 10000; i++) {
81     capturer->CaptureFrame();
82     ASSERT_EQ(num_frames_captured_, i + 1);
83   }
84 }
85 
TEST_F(BlankDetectorDesktopCapturerWrapperTest,ShouldDetectBlankFrame)86 TEST_F(BlankDetectorDesktopCapturerWrapperTest, ShouldDetectBlankFrame) {
87   wrapper_->CaptureFrame();
88   ASSERT_EQ(num_frames_captured_, 1);
89   ASSERT_EQ(last_result_, DesktopCapturer::Result::ERROR_TEMPORARY);
90   ASSERT_FALSE(last_frame_);
91 }
92 
TEST_F(BlankDetectorDesktopCapturerWrapperTest,ShouldPassBlankDetection)93 TEST_F(BlankDetectorDesktopCapturerWrapperTest, ShouldPassBlankDetection) {
94   painter_.updated_region()->AddRect(DesktopRect::MakeXYWH(0, 0, 100, 100));
95   wrapper_->CaptureFrame();
96   ASSERT_EQ(num_frames_captured_, 1);
97   ASSERT_EQ(last_result_, DesktopCapturer::Result::SUCCESS);
98   ASSERT_TRUE(last_frame_);
99 
100   painter_.updated_region()->AddRect(
101       DesktopRect::MakeXYWH(frame_width_ - 100, frame_height_ - 100, 100, 100));
102   wrapper_->CaptureFrame();
103   ASSERT_EQ(num_frames_captured_, 2);
104   ASSERT_EQ(last_result_, DesktopCapturer::Result::SUCCESS);
105   ASSERT_TRUE(last_frame_);
106 
107   painter_.updated_region()->AddRect(
108       DesktopRect::MakeXYWH(0, frame_height_ - 100, 100, 100));
109   wrapper_->CaptureFrame();
110   ASSERT_EQ(num_frames_captured_, 3);
111   ASSERT_EQ(last_result_, DesktopCapturer::Result::SUCCESS);
112   ASSERT_TRUE(last_frame_);
113 
114   painter_.updated_region()->AddRect(
115       DesktopRect::MakeXYWH(frame_width_ - 100, 0, 100, 100));
116   wrapper_->CaptureFrame();
117   ASSERT_EQ(num_frames_captured_, 4);
118   ASSERT_EQ(last_result_, DesktopCapturer::Result::SUCCESS);
119   ASSERT_TRUE(last_frame_);
120 
121   painter_.updated_region()->AddRect(DesktopRect::MakeXYWH(
122       (frame_width_ >> 1) - 50, (frame_height_ >> 1) - 50, 100, 100));
123   wrapper_->CaptureFrame();
124   ASSERT_EQ(num_frames_captured_, 5);
125   ASSERT_EQ(last_result_, DesktopCapturer::Result::SUCCESS);
126   ASSERT_TRUE(last_frame_);
127 }
128 
TEST_F(BlankDetectorDesktopCapturerWrapperTest,ShouldNotCheckAfterANonBlankFrameReceived)129 TEST_F(BlankDetectorDesktopCapturerWrapperTest,
130        ShouldNotCheckAfterANonBlankFrameReceived) {
131   wrapper_->CaptureFrame();
132   ASSERT_EQ(num_frames_captured_, 1);
133   ASSERT_EQ(last_result_, DesktopCapturer::Result::ERROR_TEMPORARY);
134   ASSERT_FALSE(last_frame_);
135 
136   painter_.updated_region()->AddRect(
137       DesktopRect::MakeXYWH(frame_width_ - 100, 0, 100, 100));
138   wrapper_->CaptureFrame();
139   ASSERT_EQ(num_frames_captured_, 2);
140   ASSERT_EQ(last_result_, DesktopCapturer::Result::SUCCESS);
141   ASSERT_TRUE(last_frame_);
142 
143   for (int i = 0; i < 100; i++) {
144     wrapper_->CaptureFrame();
145     ASSERT_EQ(num_frames_captured_, i + 3);
146     ASSERT_EQ(last_result_, DesktopCapturer::Result::SUCCESS);
147     ASSERT_TRUE(last_frame_);
148   }
149 }
150 
151 // There is no perceptible impact by using BlankDetectorDesktopCapturerWrapper.
152 // i.e. less than 0.2ms per frame.
153 // [ OK ] DISABLED_Performance (10210 ms)
154 // [ OK ] DISABLED_PerformanceComparison (8791 ms)
TEST_F(BlankDetectorDesktopCapturerWrapperTest,DISABLED_Performance)155 TEST_F(BlankDetectorDesktopCapturerWrapperTest, DISABLED_Performance) {
156   PerfTest(wrapper_.get());
157 }
158 
TEST_F(BlankDetectorDesktopCapturerWrapperTest,DISABLED_PerformanceComparison)159 TEST_F(BlankDetectorDesktopCapturerWrapperTest,
160        DISABLED_PerformanceComparison) {
161   capturer_->Start(this);
162   PerfTest(capturer_);
163 }
164 
165 }  // namespace webrtc
166