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