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/fallback_desktop_capturer_wrapper.h"
12 
13 #include <stddef.h>
14 
15 #include <memory>
16 #include <utility>
17 #include <vector>
18 
19 #include "modules/desktop_capture/desktop_capturer.h"
20 #include "modules/desktop_capture/desktop_frame_generator.h"
21 #include "modules/desktop_capture/fake_desktop_capturer.h"
22 #include "test/gtest.h"
23 
24 namespace webrtc {
25 
26 namespace {
27 
CreateDesktopCapturer(PainterDesktopFrameGenerator * frame_generator)28 std::unique_ptr<DesktopCapturer> CreateDesktopCapturer(
29     PainterDesktopFrameGenerator* frame_generator) {
30   std::unique_ptr<FakeDesktopCapturer> capturer(new FakeDesktopCapturer());
31   capturer->set_frame_generator(frame_generator);
32   return std::move(capturer);
33 }
34 
35 class FakeSharedMemory : public SharedMemory {
36  public:
37   explicit FakeSharedMemory(size_t size);
38   ~FakeSharedMemory() override;
39 
40  private:
41   static int next_id_;
42 };
43 
44 // static
45 int FakeSharedMemory::next_id_ = 0;
46 
FakeSharedMemory(size_t size)47 FakeSharedMemory::FakeSharedMemory(size_t size)
48     : SharedMemory(new char[size], size, 0, next_id_++) {}
49 
~FakeSharedMemory()50 FakeSharedMemory::~FakeSharedMemory() {
51   delete[] static_cast<char*>(data_);
52 }
53 
54 class FakeSharedMemoryFactory : public SharedMemoryFactory {
55  public:
56   FakeSharedMemoryFactory() = default;
57   ~FakeSharedMemoryFactory() override = default;
58 
59   std::unique_ptr<SharedMemory> CreateSharedMemory(size_t size) override;
60 };
61 
CreateSharedMemory(size_t size)62 std::unique_ptr<SharedMemory> FakeSharedMemoryFactory::CreateSharedMemory(
63     size_t size) {
64   return std::unique_ptr<SharedMemory>(new FakeSharedMemory(size));
65 }
66 
67 }  // namespace
68 
69 class FallbackDesktopCapturerWrapperTest : public ::testing::Test,
70                                            public DesktopCapturer::Callback {
71  public:
72   FallbackDesktopCapturerWrapperTest();
73   ~FallbackDesktopCapturerWrapperTest() override = default;
74 
75  protected:
76   std::vector<std::pair<DesktopCapturer::Result, bool>> results_;
77   FakeDesktopCapturer* main_capturer_ = nullptr;
78   FakeDesktopCapturer* secondary_capturer_ = nullptr;
79   std::unique_ptr<FallbackDesktopCapturerWrapper> wrapper_;
80 
81  private:
82   // DesktopCapturer::Callback interface
83   void OnCaptureResult(DesktopCapturer::Result result,
84                        std::unique_ptr<DesktopFrame> frame) override;
85   PainterDesktopFrameGenerator frame_generator_;
86 };
87 
FallbackDesktopCapturerWrapperTest()88 FallbackDesktopCapturerWrapperTest::FallbackDesktopCapturerWrapperTest() {
89   frame_generator_.size()->set(1024, 768);
90   std::unique_ptr<DesktopCapturer> main_capturer =
91       CreateDesktopCapturer(&frame_generator_);
92   std::unique_ptr<DesktopCapturer> secondary_capturer =
93       CreateDesktopCapturer(&frame_generator_);
94   main_capturer_ = static_cast<FakeDesktopCapturer*>(main_capturer.get());
95   secondary_capturer_ =
96       static_cast<FakeDesktopCapturer*>(secondary_capturer.get());
97   wrapper_.reset(new FallbackDesktopCapturerWrapper(
98       std::move(main_capturer), std::move(secondary_capturer)));
99   wrapper_->Start(this);
100 }
101 
OnCaptureResult(DesktopCapturer::Result result,std::unique_ptr<DesktopFrame> frame)102 void FallbackDesktopCapturerWrapperTest::OnCaptureResult(
103     DesktopCapturer::Result result,
104     std::unique_ptr<DesktopFrame> frame) {
105   results_.emplace_back(result, !!frame);
106 }
107 
TEST_F(FallbackDesktopCapturerWrapperTest,MainNeverFailed)108 TEST_F(FallbackDesktopCapturerWrapperTest, MainNeverFailed) {
109   wrapper_->CaptureFrame();
110   ASSERT_EQ(main_capturer_->num_capture_attempts(), 1);
111   ASSERT_EQ(main_capturer_->num_frames_captured(), 1);
112   ASSERT_EQ(secondary_capturer_->num_capture_attempts(), 0);
113   ASSERT_EQ(secondary_capturer_->num_frames_captured(), 0);
114   ASSERT_EQ(results_.size(), 1U);
115   ASSERT_EQ(results_[0],
116             std::make_pair(DesktopCapturer::Result::SUCCESS, true));
117 }
118 
TEST_F(FallbackDesktopCapturerWrapperTest,MainFailedTemporarily)119 TEST_F(FallbackDesktopCapturerWrapperTest, MainFailedTemporarily) {
120   wrapper_->CaptureFrame();
121   main_capturer_->set_result(DesktopCapturer::Result::ERROR_TEMPORARY);
122   wrapper_->CaptureFrame();
123   main_capturer_->set_result(DesktopCapturer::Result::SUCCESS);
124   wrapper_->CaptureFrame();
125 
126   ASSERT_EQ(main_capturer_->num_capture_attempts(), 3);
127   ASSERT_EQ(main_capturer_->num_frames_captured(), 2);
128   ASSERT_EQ(secondary_capturer_->num_capture_attempts(), 1);
129   ASSERT_EQ(secondary_capturer_->num_frames_captured(), 1);
130   ASSERT_EQ(results_.size(), 3U);
131   for (int i = 0; i < 3; i++) {
132     ASSERT_EQ(results_[i],
133               std::make_pair(DesktopCapturer::Result::SUCCESS, true));
134   }
135 }
136 
TEST_F(FallbackDesktopCapturerWrapperTest,MainFailedPermanently)137 TEST_F(FallbackDesktopCapturerWrapperTest, MainFailedPermanently) {
138   wrapper_->CaptureFrame();
139   main_capturer_->set_result(DesktopCapturer::Result::ERROR_PERMANENT);
140   wrapper_->CaptureFrame();
141   main_capturer_->set_result(DesktopCapturer::Result::SUCCESS);
142   wrapper_->CaptureFrame();
143 
144   ASSERT_EQ(main_capturer_->num_capture_attempts(), 2);
145   ASSERT_EQ(main_capturer_->num_frames_captured(), 1);
146   ASSERT_EQ(secondary_capturer_->num_capture_attempts(), 2);
147   ASSERT_EQ(secondary_capturer_->num_frames_captured(), 2);
148   ASSERT_EQ(results_.size(), 3U);
149   for (int i = 0; i < 3; i++) {
150     ASSERT_EQ(results_[i],
151               std::make_pair(DesktopCapturer::Result::SUCCESS, true));
152   }
153 }
154 
TEST_F(FallbackDesktopCapturerWrapperTest,BothFailed)155 TEST_F(FallbackDesktopCapturerWrapperTest, BothFailed) {
156   wrapper_->CaptureFrame();
157   main_capturer_->set_result(DesktopCapturer::Result::ERROR_PERMANENT);
158   wrapper_->CaptureFrame();
159   main_capturer_->set_result(DesktopCapturer::Result::SUCCESS);
160   wrapper_->CaptureFrame();
161   secondary_capturer_->set_result(DesktopCapturer::Result::ERROR_TEMPORARY);
162   wrapper_->CaptureFrame();
163   secondary_capturer_->set_result(DesktopCapturer::Result::ERROR_PERMANENT);
164   wrapper_->CaptureFrame();
165   wrapper_->CaptureFrame();
166 
167   ASSERT_EQ(main_capturer_->num_capture_attempts(), 2);
168   ASSERT_EQ(main_capturer_->num_frames_captured(), 1);
169   ASSERT_EQ(secondary_capturer_->num_capture_attempts(), 5);
170   ASSERT_EQ(secondary_capturer_->num_frames_captured(), 2);
171   ASSERT_EQ(results_.size(), 6U);
172   for (int i = 0; i < 3; i++) {
173     ASSERT_EQ(results_[i],
174               std::make_pair(DesktopCapturer::Result::SUCCESS, true));
175   }
176   ASSERT_EQ(results_[3],
177             std::make_pair(DesktopCapturer::Result::ERROR_TEMPORARY, false));
178   ASSERT_EQ(results_[4],
179             std::make_pair(DesktopCapturer::Result::ERROR_PERMANENT, false));
180   ASSERT_EQ(results_[5],
181             std::make_pair(DesktopCapturer::Result::ERROR_PERMANENT, false));
182 }
183 
TEST_F(FallbackDesktopCapturerWrapperTest,WithSharedMemory)184 TEST_F(FallbackDesktopCapturerWrapperTest, WithSharedMemory) {
185   wrapper_->SetSharedMemoryFactory(
186       std::unique_ptr<SharedMemoryFactory>(new FakeSharedMemoryFactory()));
187   wrapper_->CaptureFrame();
188   main_capturer_->set_result(DesktopCapturer::Result::ERROR_TEMPORARY);
189   wrapper_->CaptureFrame();
190   main_capturer_->set_result(DesktopCapturer::Result::SUCCESS);
191   wrapper_->CaptureFrame();
192   main_capturer_->set_result(DesktopCapturer::Result::ERROR_PERMANENT);
193   wrapper_->CaptureFrame();
194   wrapper_->CaptureFrame();
195 
196   ASSERT_EQ(main_capturer_->num_capture_attempts(), 4);
197   ASSERT_EQ(main_capturer_->num_frames_captured(), 2);
198   ASSERT_EQ(secondary_capturer_->num_capture_attempts(), 3);
199   ASSERT_EQ(secondary_capturer_->num_frames_captured(), 3);
200   ASSERT_EQ(results_.size(), 5U);
201   for (int i = 0; i < 5; i++) {
202     ASSERT_EQ(results_[i],
203               std::make_pair(DesktopCapturer::Result::SUCCESS, true));
204   }
205 }
206 
207 }  // namespace webrtc
208