OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
| 11 #include <string.h> |
| 12 |
| 13 #include <algorithm> |
11 #include <memory> | 14 #include <memory> |
12 #include <utility> | 15 #include <utility> |
| 16 #include <vector> |
13 | 17 |
14 #include "webrtc/modules/desktop_capture/screen_capturer.h" | 18 #include "webrtc/modules/desktop_capture/screen_capturer.h" |
15 | 19 |
16 #include "testing/gmock/include/gmock/gmock.h" | 20 #include "testing/gmock/include/gmock/gmock.h" |
17 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gtest/include/gtest/gtest.h" |
18 #include "webrtc/base/constructormagic.h" | 22 #include "webrtc/base/constructormagic.h" |
19 #include "webrtc/base/logging.h" | 23 #include "webrtc/base/logging.h" |
20 #include "webrtc/modules/desktop_capture/desktop_capture_options.h" | 24 #include "webrtc/modules/desktop_capture/desktop_capture_options.h" |
21 #include "webrtc/modules/desktop_capture/desktop_frame.h" | 25 #include "webrtc/modules/desktop_capture/desktop_frame.h" |
22 #include "webrtc/modules/desktop_capture/desktop_region.h" | 26 #include "webrtc/modules/desktop_capture/desktop_region.h" |
23 #include "webrtc/modules/desktop_capture/screen_capturer_mock_objects.h" | 27 #include "webrtc/modules/desktop_capture/screen_capturer_mock_objects.h" |
| 28 #include "webrtc/modules/desktop_capture/screen_painter.h" |
| 29 #include "webrtc/system_wrappers/include/sleep.h" |
24 | 30 |
25 #if defined(WEBRTC_WIN) | 31 #if defined(WEBRTC_WIN) |
26 #include "webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h" | 32 #include "webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h" |
27 #endif // defined(WEBRTC_WIN) | 33 #endif // defined(WEBRTC_WIN) |
28 | 34 |
29 using ::testing::_; | 35 using ::testing::_; |
30 using ::testing::AnyNumber; | 36 using ::testing::AnyNumber; |
31 using ::testing::Return; | 37 using ::testing::Return; |
32 | 38 |
33 const int kTestSharedMemoryId = 123; | 39 const int kTestSharedMemoryId = 123; |
34 | 40 |
35 namespace webrtc { | 41 namespace webrtc { |
36 | 42 |
| 43 namespace { |
| 44 |
| 45 ACTION_P(SaveUniquePtrArg, dest) { |
| 46 *dest = std::move(*arg1); |
| 47 } |
| 48 |
| 49 // Expects |capturer| to successfully capture a frame, and returns it. |
| 50 std::unique_ptr<DesktopFrame> CaptureFrame( |
| 51 ScreenCapturer* capturer, |
| 52 MockScreenCapturerCallback* callback) { |
| 53 std::unique_ptr<DesktopFrame> frame; |
| 54 EXPECT_CALL(*callback, |
| 55 OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _)) |
| 56 .WillOnce(SaveUniquePtrArg(&frame)); |
| 57 capturer->Capture(DesktopRegion()); |
| 58 EXPECT_TRUE(frame); |
| 59 return frame; |
| 60 } |
| 61 |
| 62 // Expects color in |rect| of |frame| is |color|. |
| 63 void ExpectPixelsAreColoredBy(const DesktopFrame& frame, |
| 64 DesktopRect rect, |
| 65 ScreenPainter::Color color) { |
| 66 uint8_t* row = frame.GetFrameDataAtPos(rect.top_left()); |
| 67 for (int i = 0; i < rect.height(); i++) { |
| 68 uint8_t* column = row; |
| 69 for (int j = 0; j < rect.width(); j++) { |
| 70 ASSERT_EQ(color, column); |
| 71 column += DesktopFrame::kBytesPerPixel; |
| 72 } |
| 73 row += frame.stride(); |
| 74 } |
| 75 } |
| 76 |
| 77 // Finds the visible region and offset of ScreenDrawer drawable region in |
| 78 // ScreenCapturer reachable area. The top left of the DesktopRect returned is |
| 79 // the offset of ScreenDrawer drawable region, which maps to (0, 0) of |
| 80 // ScreenDrawer::DrawableRegion(). The size of the DesktopRect indicates the |
| 81 // size of visible region. So to ensure rendering a shape in the visible area of |
| 82 // ScreenCapturer, you can randomize points within the DesktopRect::size() and |
| 83 // use DesktopRect::Translate(-top_left().left(), -top_left().top()) or |
| 84 // DesktopVector::subtract(top_left()) to translate into the coordinate of |
| 85 // ScreenDrawer. This function returns an empty DesktopRect if calibration |
| 86 // failed. |
| 87 DesktopRect CalibrateScreenDrawerPosition( |
| 88 ScreenPainter* painter, |
| 89 ScreenCapturer* capturer, |
| 90 MockScreenCapturerCallback* callback) { |
| 91 const int kAnchorSize = 20; |
| 92 if (painter->DrawableRegion().width() < kAnchorSize || |
| 93 painter->DrawableRegion().height() < 1) { |
| 94 LOG(LS_WARNING) << "DrawableRegion is too small for calibration."; |
| 95 return DesktopRect(); |
| 96 } |
| 97 std::vector<ScreenPainter::Color> anchor_colors; |
| 98 painter->Clear(); |
| 99 painter->DrawColorfulHorizontalLine(DesktopVector(), kAnchorSize, |
| 100 &anchor_colors); |
| 101 // We do not need a very accurate positiin, so reduce the sample rate by |
| 102 // 1/256. This usually does not make too much difference. |
| 103 for (int i = std::max(painter->DrawableRegion().width(), |
| 104 painter->DrawableRegion().height()) - |
| 105 1; |
| 106 i > 0; i -= 16) { |
| 107 for (int j = i; j < std::max(painter->DrawableRegion().width(), |
| 108 painter->DrawableRegion().height()) - |
| 109 1; |
| 110 j += anchor_colors.size() * 16) { |
| 111 painter->DrawColorfulHorizontalLine(DesktopVector(j, i), anchor_colors); |
| 112 } |
| 113 } |
| 114 painter->WaitForPendingPaintings(); |
| 115 |
| 116 std::unique_ptr<DesktopFrame> frame = CaptureFrame(capturer, callback); |
| 117 painter->Clear(); |
| 118 if (!frame) { |
| 119 return DesktopRect(); |
| 120 } |
| 121 |
| 122 const uint8_t* const end = |
| 123 frame->data() + frame->stride() * frame->size().height() - |
| 124 anchor_colors.size() * sizeof(ScreenPainter::Color); |
| 125 DesktopVector top_left(-1, -1); |
| 126 DesktopVector right_bottom; |
| 127 for (const uint8_t* i = frame->data(); i < end; |
| 128 i += DesktopFrame::kBytesPerPixel) { |
| 129 if (ScreenPainter::Color::PixelsMatch(anchor_colors, i)) { |
| 130 right_bottom = frame->GetPosAtFrameData(i); |
| 131 if (top_left.x() < 0 && top_left.y() < 0) { |
| 132 top_left = right_bottom; |
| 133 } |
| 134 } |
| 135 } |
| 136 |
| 137 if (top_left.x() >= 0 && top_left.y() >= 0) { |
| 138 return DesktopRect::MakeLTRB(top_left, right_bottom); |
| 139 } |
| 140 |
| 141 return DesktopRect(); |
| 142 } |
| 143 |
| 144 } // namespace |
| 145 |
37 class ScreenCapturerTest : public testing::Test { | 146 class ScreenCapturerTest : public testing::Test { |
38 public: | 147 public: |
39 void SetUp() override { | 148 void SetUp() override { |
40 capturer_.reset( | 149 capturer_.reset( |
41 ScreenCapturer::Create(DesktopCaptureOptions::CreateDefault())); | 150 ScreenCapturer::Create(DesktopCaptureOptions::CreateDefault())); |
42 } | 151 } |
43 | 152 |
44 protected: | 153 protected: |
45 std::unique_ptr<ScreenCapturer> capturer_; | 154 std::unique_ptr<ScreenCapturer> capturer_; |
46 MockScreenCapturerCallback callback_; | 155 MockScreenCapturerCallback callback_; |
(...skipping 20 matching lines...) Expand all Loading... |
67 | 176 |
68 std::unique_ptr<SharedMemory> CreateSharedMemory(size_t size) override { | 177 std::unique_ptr<SharedMemory> CreateSharedMemory(size_t size) override { |
69 return std::unique_ptr<SharedMemory>( | 178 return std::unique_ptr<SharedMemory>( |
70 new FakeSharedMemory(new char[size], size)); | 179 new FakeSharedMemory(new char[size], size)); |
71 } | 180 } |
72 | 181 |
73 private: | 182 private: |
74 RTC_DISALLOW_COPY_AND_ASSIGN(FakeSharedMemoryFactory); | 183 RTC_DISALLOW_COPY_AND_ASSIGN(FakeSharedMemoryFactory); |
75 }; | 184 }; |
76 | 185 |
77 ACTION_P(SaveUniquePtrArg, dest) { | |
78 *dest = std::move(*arg1); | |
79 } | |
80 | |
81 TEST_F(ScreenCapturerTest, GetScreenListAndSelectScreen) { | 186 TEST_F(ScreenCapturerTest, GetScreenListAndSelectScreen) { |
82 webrtc::ScreenCapturer::ScreenList screens; | 187 webrtc::ScreenCapturer::ScreenList screens; |
83 EXPECT_TRUE(capturer_->GetScreenList(&screens)); | 188 EXPECT_TRUE(capturer_->GetScreenList(&screens)); |
84 for (webrtc::ScreenCapturer::ScreenList::iterator it = screens.begin(); | 189 for (webrtc::ScreenCapturer::ScreenList::iterator it = screens.begin(); |
85 it != screens.end(); ++it) { | 190 it != screens.end(); ++it) { |
86 EXPECT_TRUE(capturer_->SelectScreen(it->id)); | 191 EXPECT_TRUE(capturer_->SelectScreen(it->id)); |
87 } | 192 } |
88 } | 193 } |
89 | 194 |
90 TEST_F(ScreenCapturerTest, StartCapturer) { | 195 TEST_F(ScreenCapturerTest, StartCapturer) { |
(...skipping 19 matching lines...) Expand all Loading... |
110 | 215 |
111 // Verify that the region contains whole screen. | 216 // Verify that the region contains whole screen. |
112 EXPECT_FALSE(frame->updated_region().is_empty()); | 217 EXPECT_FALSE(frame->updated_region().is_empty()); |
113 DesktopRegion::Iterator it(frame->updated_region()); | 218 DesktopRegion::Iterator it(frame->updated_region()); |
114 ASSERT_TRUE(!it.IsAtEnd()); | 219 ASSERT_TRUE(!it.IsAtEnd()); |
115 EXPECT_TRUE(it.rect().equals(DesktopRect::MakeSize(frame->size()))); | 220 EXPECT_TRUE(it.rect().equals(DesktopRect::MakeSize(frame->size()))); |
116 it.Advance(); | 221 it.Advance(); |
117 EXPECT_TRUE(it.IsAtEnd()); | 222 EXPECT_TRUE(it.IsAtEnd()); |
118 } | 223 } |
119 | 224 |
| 225 TEST_F(ScreenCapturerTest, CaptureUpdatedRegion) { |
| 226 std::unique_ptr<ScreenPainter> painter = ScreenPainter::Create(); |
| 227 if (!painter || painter->DrawableRegion().is_empty()) { |
| 228 LOG(LS_WARNING) << "No ScreenPainter implementation for current platform."; |
| 229 return; |
| 230 } |
| 231 capturer_->Start(&callback_); |
| 232 |
| 233 const DesktopRect anchor = |
| 234 CalibrateScreenDrawerPosition(painter.get(), capturer_.get(), &callback_); |
| 235 if (anchor.is_empty()) { |
| 236 LOG(LS_WARNING) << "Failed to calibrate ScreenDrawer, it usually means " |
| 237 "ScreenDrawer cannot draw in ScreenCapturer reachable " |
| 238 "area."; |
| 239 return; |
| 240 } |
| 241 |
| 242 painter->Clear(); |
| 243 ScreenPainter::Color color; |
| 244 DesktopRect rect; |
| 245 painter->DrawRandomColorRectangleIn(anchor.size(), &color, &rect); |
| 246 rect.Translate(anchor.top_left()); |
| 247 painter->WaitForPendingPaintings(); |
| 248 std::unique_ptr<DesktopFrame> frame = |
| 249 CaptureFrame(capturer_.get(), &callback_); |
| 250 if (!frame) { |
| 251 return; |
| 252 } |
| 253 |
| 254 // updated_region() should cover the painted area. |
| 255 DesktopRegion updated_region(frame->updated_region()); |
| 256 updated_region.IntersectWith(rect); |
| 257 ASSERT_TRUE(updated_region.Equals(DesktopRegion(rect))); |
| 258 |
| 259 // Color in the |rect| should be |color|. |
| 260 ExpectPixelsAreColoredBy(*frame, rect, color); |
| 261 } |
| 262 |
120 #if defined(WEBRTC_WIN) | 263 #if defined(WEBRTC_WIN) |
121 | 264 |
122 TEST_F(ScreenCapturerTest, UseSharedBuffers) { | 265 TEST_F(ScreenCapturerTest, UseSharedBuffers) { |
123 std::unique_ptr<DesktopFrame> frame; | 266 std::unique_ptr<DesktopFrame> frame; |
124 EXPECT_CALL(callback_, | 267 EXPECT_CALL(callback_, |
125 OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _)) | 268 OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _)) |
126 .WillOnce(SaveUniquePtrArg(&frame)); | 269 .WillOnce(SaveUniquePtrArg(&frame)); |
127 | 270 |
128 capturer_->Start(&callback_); | 271 capturer_->Start(&callback_); |
129 capturer_->SetSharedMemoryFactory( | 272 capturer_->SetSharedMemoryFactory( |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 std::unique_ptr<SharedMemoryFactory>(new FakeSharedMemoryFactory())); | 333 std::unique_ptr<SharedMemoryFactory>(new FakeSharedMemoryFactory())); |
191 capturer_->Capture(DesktopRegion()); | 334 capturer_->Capture(DesktopRegion()); |
192 ASSERT_TRUE(frame); | 335 ASSERT_TRUE(frame); |
193 ASSERT_TRUE(frame->shared_memory()); | 336 ASSERT_TRUE(frame->shared_memory()); |
194 EXPECT_EQ(frame->shared_memory()->id(), kTestSharedMemoryId); | 337 EXPECT_EQ(frame->shared_memory()->id(), kTestSharedMemoryId); |
195 } | 338 } |
196 | 339 |
197 #endif // defined(WEBRTC_WIN) | 340 #endif // defined(WEBRTC_WIN) |
198 | 341 |
199 } // namespace webrtc | 342 } // namespace webrtc |
OLD | NEW |