screen_capturer_unittest.cc (7025B)
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 11 #include <cstddef> 12 #include <memory> 13 14 #include "modules/desktop_capture/desktop_capture_options.h" 15 #include "modules/desktop_capture/desktop_capturer.h" 16 #include "modules/desktop_capture/desktop_frame.h" 17 #include "modules/desktop_capture/desktop_geometry.h" 18 #include "modules/desktop_capture/desktop_region.h" 19 #include "modules/desktop_capture/mock_desktop_capturer_callback.h" 20 #include "modules/desktop_capture/shared_memory.h" 21 #include "rtc_base/logging.h" // IWYU pragma: keep 22 #include "test/gmock.h" 23 #include "test/gtest.h" 24 25 #if defined(WEBRTC_WIN) 26 #include "modules/desktop_capture/win/screen_capturer_win_directx.h" 27 #endif // defined(WEBRTC_WIN) 28 29 using ::testing::_; 30 31 constexpr int kTestSharedMemoryId = 123; 32 33 namespace webrtc { 34 35 class ScreenCapturerTest : public ::testing::Test { 36 public: 37 void SetUp() override { 38 capturer_ = DesktopCapturer::CreateScreenCapturer( 39 DesktopCaptureOptions::CreateDefault()); 40 ASSERT_TRUE(capturer_); 41 } 42 43 protected: 44 #if defined(WEBRTC_WIN) 45 // Enable allow_directx_capturer in DesktopCaptureOptions, but let 46 // DesktopCapturer::CreateScreenCapturer decide whether a DirectX capturer 47 // should be used. 48 void MaybeCreateDirectxCapturer() { 49 DesktopCaptureOptions options(DesktopCaptureOptions::CreateDefault()); 50 options.set_allow_directx_capturer(true); 51 capturer_ = DesktopCapturer::CreateScreenCapturer(options); 52 } 53 54 bool CreateDirectxCapturer() { 55 if (!ScreenCapturerWinDirectx::IsSupported()) { 56 RTC_LOG(LS_WARNING) << "Directx capturer is not supported"; 57 return false; 58 } 59 60 MaybeCreateDirectxCapturer(); 61 return true; 62 } 63 #endif // defined(WEBRTC_WIN) 64 65 std::unique_ptr<DesktopCapturer> capturer_; 66 MockDesktopCapturerCallback callback_; 67 }; 68 69 class FakeSharedMemory : public SharedMemory { 70 public: 71 FakeSharedMemory(char* buffer, size_t size) 72 : SharedMemory(buffer, size, 0, kTestSharedMemoryId), buffer_(buffer) {} 73 ~FakeSharedMemory() override { delete[] buffer_; } 74 75 FakeSharedMemory(const FakeSharedMemory&) = delete; 76 FakeSharedMemory& operator=(const FakeSharedMemory&) = delete; 77 78 private: 79 char* buffer_; 80 }; 81 82 class FakeSharedMemoryFactory : public SharedMemoryFactory { 83 public: 84 FakeSharedMemoryFactory() {} 85 ~FakeSharedMemoryFactory() override {} 86 87 FakeSharedMemoryFactory(const FakeSharedMemoryFactory&) = delete; 88 FakeSharedMemoryFactory& operator=(const FakeSharedMemoryFactory&) = delete; 89 90 std::unique_ptr<SharedMemory> CreateSharedMemory(size_t size) override { 91 return std::unique_ptr<SharedMemory>( 92 new FakeSharedMemory(new char[size], size)); 93 } 94 }; 95 96 ACTION_P(SaveUniquePtrArg, dest) { 97 *dest = std::move(*arg1); 98 } 99 100 // TODO(bugs.webrtc.org/12950): Re-enable when libc++ issue is fixed. 101 #if defined(WEBRTC_LINUX) && defined(MEMORY_SANITIZER) 102 #define MAYBE_GetScreenListAndSelectScreen DISABLED_GetScreenListAndSelectScreen 103 #else 104 #define MAYBE_GetScreenListAndSelectScreen GetScreenListAndSelectScreen 105 #endif 106 TEST_F(ScreenCapturerTest, MAYBE_GetScreenListAndSelectScreen) { 107 DesktopCapturer::SourceList screens; 108 EXPECT_TRUE(capturer_->GetSourceList(&screens)); 109 for (const auto& screen : screens) { 110 EXPECT_TRUE(capturer_->SelectSource(screen.id)); 111 } 112 } 113 114 // Flaky on Linux. See: crbug.com/webrtc/7830 115 #if defined(WEBRTC_LINUX) 116 #define MAYBE_StartCapturer DISABLED_StartCaptuerer 117 #else 118 #define MAYBE_StartCapturer StartCapturer 119 #endif 120 TEST_F(ScreenCapturerTest, MAYBE_StartCapturer) { 121 capturer_->Start(&callback_); 122 } 123 124 #if defined(WEBRTC_LINUX) 125 #define MAYBE_Capture DISABLED_Capture 126 #else 127 #define MAYBE_Capture Capture 128 #endif 129 TEST_F(ScreenCapturerTest, MAYBE_Capture) { 130 // Assume that Start() treats the screen as invalid initially. 131 std::unique_ptr<DesktopFrame> frame; 132 EXPECT_CALL(callback_, 133 OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _)) 134 .WillOnce(SaveUniquePtrArg(&frame)); 135 136 capturer_->Start(&callback_); 137 capturer_->CaptureFrame(); 138 139 ASSERT_TRUE(frame); 140 EXPECT_GT(frame->size().width(), 0); 141 EXPECT_GT(frame->size().height(), 0); 142 EXPECT_GE(frame->stride(), 143 frame->size().width() * DesktopFrame::kBytesPerPixel); 144 EXPECT_TRUE(frame->shared_memory() == nullptr); 145 146 // Verify that the region contains whole screen. 147 EXPECT_FALSE(frame->updated_region().is_empty()); 148 DesktopRegion::Iterator it(frame->updated_region()); 149 ASSERT_TRUE(!it.IsAtEnd()); 150 EXPECT_TRUE(it.rect().equals(DesktopRect::MakeSize(frame->size()))); 151 it.Advance(); 152 EXPECT_TRUE(it.IsAtEnd()); 153 } 154 155 #if defined(WEBRTC_WIN) 156 157 TEST_F(ScreenCapturerTest, UseSharedBuffers) { 158 std::unique_ptr<DesktopFrame> frame; 159 EXPECT_CALL(callback_, 160 OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _)) 161 .WillOnce(SaveUniquePtrArg(&frame)); 162 163 capturer_->Start(&callback_); 164 capturer_->SetSharedMemoryFactory( 165 std::unique_ptr<SharedMemoryFactory>(new FakeSharedMemoryFactory())); 166 capturer_->CaptureFrame(); 167 168 ASSERT_TRUE(frame); 169 ASSERT_TRUE(frame->shared_memory()); 170 EXPECT_EQ(frame->shared_memory()->id(), kTestSharedMemoryId); 171 } 172 173 TEST_F(ScreenCapturerTest, GdiIsDefault) { 174 std::unique_ptr<DesktopFrame> frame; 175 EXPECT_CALL(callback_, 176 OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _)) 177 .WillOnce(SaveUniquePtrArg(&frame)); 178 179 capturer_->Start(&callback_); 180 capturer_->CaptureFrame(); 181 ASSERT_TRUE(frame); 182 EXPECT_EQ(frame->capturer_id(), DesktopCapturerId::kScreenCapturerWinGdi); 183 } 184 185 TEST_F(ScreenCapturerTest, UseDirectxCapturer) { 186 if (!CreateDirectxCapturer()) { 187 return; 188 } 189 190 std::unique_ptr<DesktopFrame> frame; 191 EXPECT_CALL(callback_, 192 OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _)) 193 .WillOnce(SaveUniquePtrArg(&frame)); 194 195 capturer_->Start(&callback_); 196 capturer_->CaptureFrame(); 197 ASSERT_TRUE(frame); 198 EXPECT_EQ(frame->capturer_id(), DesktopCapturerId::kScreenCapturerWinDirectx); 199 } 200 201 TEST_F(ScreenCapturerTest, UseDirectxCapturerWithSharedBuffers) { 202 if (!CreateDirectxCapturer()) { 203 return; 204 } 205 206 std::unique_ptr<DesktopFrame> frame; 207 EXPECT_CALL(callback_, 208 OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _)) 209 .WillOnce(SaveUniquePtrArg(&frame)); 210 211 capturer_->Start(&callback_); 212 capturer_->SetSharedMemoryFactory( 213 std::unique_ptr<SharedMemoryFactory>(new FakeSharedMemoryFactory())); 214 capturer_->CaptureFrame(); 215 ASSERT_TRUE(frame); 216 ASSERT_TRUE(frame->shared_memory()); 217 EXPECT_EQ(frame->shared_memory()->id(), kTestSharedMemoryId); 218 EXPECT_EQ(frame->capturer_id(), DesktopCapturerId::kScreenCapturerWinDirectx); 219 } 220 221 #endif // defined(WEBRTC_WIN) 222 223 } // namespace webrtc