OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright (c) 2016 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 "webrtc/modules/desktop_capture/screen_capturer_mock_objects.h" |
| 12 |
| 13 #include <stdint.h> |
| 14 #include <string.h> |
| 15 |
| 16 #include <utility> |
| 17 |
| 18 #include "webrtc/base/random.h" |
| 19 #include "webrtc/base/timeutils.h" |
| 20 #include "webrtc/modules/desktop_capture/shared_desktop_frame.h" |
| 21 |
| 22 namespace webrtc { |
| 23 |
| 24 namespace { |
| 25 |
| 26 // Creates a DesktopFrame according to the input |factory|, and paints it to |
| 27 // white. |
| 28 std::unique_ptr<DesktopFrame> CreateDesktopFrame( |
| 29 DesktopSize size, |
| 30 SharedMemoryFactory* factory) { |
| 31 std::unique_ptr<DesktopFrame> frame( |
| 32 factory ? |
| 33 SharedMemoryDesktopFrame::Create(size, factory).release() : |
| 34 new BasicDesktopFrame(size)); |
| 35 memset(frame->data(), 0, frame->stride() * frame->size().height()); |
| 36 return SharedDesktopFrame::Wrap(std::move(frame)); |
| 37 } |
| 38 |
| 39 // Paints pixels in |rect| of |frame| to |color|. |
| 40 void PaintRect(DesktopFrame* frame, DesktopRect rect, uint32_t color) { |
| 41 static_assert(DesktopFrame::kBytesPerPixel == sizeof(uint32_t), |
| 42 "kBytesPerPixel should be 4."); |
| 43 ASSERT_TRUE(frame->size().width() >= rect.width() && |
| 44 frame->size().height() >= rect.height()); |
| 45 int row = rect.top() * frame->stride(); |
| 46 for (int i = 0; i < rect.height(); i++) { |
| 47 int column = rect.left() * DesktopFrame::kBytesPerPixel; |
| 48 for (int j = 0; j < rect.width(); j++) { |
| 49 memcpy(&frame->data()[row + column], &color, sizeof(color)); |
| 50 column += DesktopFrame::kBytesPerPixel; |
| 51 } |
| 52 row += frame->stride(); |
| 53 } |
| 54 } |
| 55 |
| 56 // Paints pixels in |region| of |frame| to |color|. |
| 57 void PaintRegion(DesktopFrame* frame, |
| 58 const DesktopRegion& region, |
| 59 uint32_t color) { |
| 60 for (DesktopRegion::Iterator it(region); !it.IsAtEnd(); it.Advance()) { |
| 61 PaintRect(frame, it.rect(), color); |
| 62 } |
| 63 } |
| 64 |
| 65 // Sets dirty region of |frame| to |dirty_region|. If |enlarge_dirty_region| is |
| 66 // true, this function will randomly enlarge each DesktopRect in |dirty_region|. |
| 67 // But the enlarged DesktopRegion won't excceed the frame->size(). |
| 68 void SetDirtyRegion(DesktopFrame* frame, |
| 69 const DesktopRegion& dirty_region, |
| 70 bool enlarge_dirty_region) { |
| 71 DesktopRect screen_rect = DesktopRect::MakeSize(frame->size()); |
| 72 Random random(rtc::TimeMicros()); |
| 73 frame->mutable_updated_region()->Clear(); |
| 74 for (DesktopRegion::Iterator it(dirty_region); !it.IsAtEnd(); it.Advance()) { |
| 75 DesktopRect rect = it.rect(); |
| 76 if (enlarge_dirty_region) { |
| 77 rect = DesktopRect::MakeLTRB(rect.left() - random.Rand(20), |
| 78 rect.top() - random.Rand(20), |
| 79 rect.right() + random.Rand(20), |
| 80 rect.bottom() + random.Rand(20)); |
| 81 rect.IntersectWith(screen_rect); |
| 82 } |
| 83 frame->mutable_updated_region()->AddRect(rect); |
| 84 } |
| 85 } |
| 86 |
| 87 } // namespace |
| 88 |
| 89 MockScreenCapturer::MockScreenCapturer() |
| 90 : callback_(nullptr), |
| 91 size_(1024, 768), |
| 92 result_(Result::SUCCESS), |
| 93 return_frame_(true), |
| 94 provide_dirty_region_hints_(false), |
| 95 enlarge_dirty_region_(false) { |
| 96 ON_CALL(*this, Start(testing::_)) |
| 97 .WillByDefault(testing::Invoke([this](Callback* callback) { |
| 98 callback_ = callback; |
| 99 })); |
| 100 |
| 101 ON_CALL(*this, Capture(testing::_)) |
| 102 .WillByDefault(testing::Invoke([this](const DesktopRegion& region) { |
| 103 // A typical ScreenCapturer won't use the |region| parameter. |
| 104 ASSERT_TRUE(callback_); |
| 105 if (return_frame_) { |
| 106 std::unique_ptr<DesktopFrame> frame = |
| 107 CreateDesktopFrame(size_, shared_memory_factory_.get()); |
| 108 PaintRegion(frame.get(), dirty_region_, UINT32_MAX); |
| 109 if (provide_dirty_region_hints_) { |
| 110 SetDirtyRegion(frame.get(), dirty_region_, enlarge_dirty_region_); |
| 111 } |
| 112 dirty_region_.Clear(); |
| 113 callback_->OnCaptureResult(result_, std::move(frame)); |
| 114 } else { |
| 115 callback_->OnCaptureResult(result_, std::unique_ptr<DesktopFrame>()); |
| 116 } |
| 117 })); |
| 118 |
| 119 ON_CALL(*this, GetScreenList(testing::_)) |
| 120 .WillByDefault(testing::Return(true)); |
| 121 |
| 122 ON_CALL(*this, SelectScreen(testing::_)) |
| 123 .WillByDefault(testing::Invoke([](ScreenId id) { |
| 124 return id == kFullDesktopScreenId; |
| 125 })); |
| 126 } |
| 127 |
| 128 MockScreenCapturer::~MockScreenCapturer() = default; |
| 129 |
| 130 void MockScreenCapturer::SetSharedMemoryFactory( |
| 131 std::unique_ptr<SharedMemoryFactory> shared_memory_factory) { |
| 132 shared_memory_factory_ = std::move(shared_memory_factory); |
| 133 } |
| 134 |
| 135 } // namespace webrtc |
OLD | NEW |