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/desktop_frame_generator.h" |
| 12 |
| 13 #include <stdint.h> |
| 14 #include <string.h> |
| 15 |
| 16 #include <memory> |
| 17 |
| 18 #include "webrtc/base/random.h" |
| 19 #include "webrtc/base/timeutils.h" |
| 20 |
| 21 namespace webrtc { |
| 22 |
| 23 namespace { |
| 24 |
| 25 // Sets |updated_region| to |frame|. If |enlarge_updated_region| is |
| 26 // true, this function will randomly enlarge each DesktopRect in |
| 27 // |updated_region|. But the enlarged DesktopRegion won't excceed the |
| 28 // frame->size(). If |add_random_updated_region| is true, several random |
| 29 // rectangles will also be included in |frame|. |
| 30 void SetUpdatedRegion(DesktopFrame* frame, |
| 31 const DesktopRegion& updated_region, |
| 32 bool enlarge_updated_region, |
| 33 int enlarge_range, |
| 34 bool add_random_updated_region) { |
| 35 const DesktopRect screen_rect = DesktopRect::MakeSize(frame->size()); |
| 36 Random random(rtc::TimeMicros()); |
| 37 frame->mutable_updated_region()->Clear(); |
| 38 for (DesktopRegion::Iterator it(updated_region); !it.IsAtEnd(); |
| 39 it.Advance()) { |
| 40 DesktopRect rect = it.rect(); |
| 41 if (enlarge_updated_region && enlarge_range > 0) { |
| 42 rect.Extend(random.Rand(enlarge_range), random.Rand(enlarge_range), |
| 43 random.Rand(enlarge_range), random.Rand(enlarge_range)); |
| 44 rect.IntersectWith(screen_rect); |
| 45 } |
| 46 frame->mutable_updated_region()->AddRect(rect); |
| 47 } |
| 48 |
| 49 if (add_random_updated_region) { |
| 50 for (int i = random.Rand(10); i >= 0; i--) { |
| 51 // At least a 1 x 1 updated region. |
| 52 const int left = random.Rand(0, frame->size().width() - 2); |
| 53 const int top = random.Rand(0, frame->size().height() - 2); |
| 54 const int right = random.Rand(left + 1, frame->size().width()); |
| 55 const int bottom = random.Rand(top + 1, frame->size().height()); |
| 56 frame->mutable_updated_region()->AddRect( |
| 57 DesktopRect::MakeLTRB(left, top, right, bottom)); |
| 58 } |
| 59 } |
| 60 } |
| 61 |
| 62 // Paints pixels in |rect| of |frame| to |color|. |
| 63 void PaintRect(DesktopFrame* frame, DesktopRect rect, uint32_t color) { |
| 64 static_assert(DesktopFrame::kBytesPerPixel == sizeof(uint32_t), |
| 65 "kBytesPerPixel should be 4."); |
| 66 RTC_DCHECK(frame->size().width() >= rect.right() && |
| 67 frame->size().height() >= rect.bottom()); |
| 68 uint8_t* row = frame->GetFrameDataAtPos(rect.top_left()); |
| 69 for (int i = 0; i < rect.height(); i++) { |
| 70 uint32_t* column = reinterpret_cast<uint32_t*>(row); |
| 71 for (int j = 0; j < rect.width(); j++) { |
| 72 column[j] = color; |
| 73 } |
| 74 row += frame->stride(); |
| 75 } |
| 76 } |
| 77 |
| 78 // Paints pixels in |region| of |frame| to |color|. |
| 79 void PaintRegion(DesktopFrame* frame, DesktopRegion* region, uint32_t color) { |
| 80 region->IntersectWith(DesktopRect::MakeSize(frame->size())); |
| 81 for (DesktopRegion::Iterator it(*region); !it.IsAtEnd(); it.Advance()) { |
| 82 PaintRect(frame, it.rect(), color); |
| 83 } |
| 84 } |
| 85 |
| 86 } // namespace |
| 87 |
| 88 DesktopFrameGenerator::DesktopFrameGenerator() {} |
| 89 DesktopFrameGenerator::~DesktopFrameGenerator() {} |
| 90 |
| 91 DesktopFramePainter::DesktopFramePainter() {} |
| 92 DesktopFramePainter::~DesktopFramePainter() {} |
| 93 |
| 94 PainterDesktopFrameGenerator::PainterDesktopFrameGenerator() |
| 95 : size_(1024, 768), |
| 96 return_frame_(true), |
| 97 provide_updated_region_hints_(false), |
| 98 enlarge_updated_region_(false), |
| 99 enlarge_range_(20), |
| 100 add_random_updated_region_(false), |
| 101 painter_(nullptr) {} |
| 102 PainterDesktopFrameGenerator::~PainterDesktopFrameGenerator() {} |
| 103 |
| 104 std::unique_ptr<DesktopFrame> PainterDesktopFrameGenerator::GetNextFrame( |
| 105 SharedMemoryFactory* factory) { |
| 106 if (!return_frame_) { |
| 107 return nullptr; |
| 108 } |
| 109 |
| 110 std::unique_ptr<DesktopFrame> frame = std::unique_ptr<DesktopFrame>( |
| 111 factory ? SharedMemoryDesktopFrame::Create(size_, factory).release() |
| 112 : new BasicDesktopFrame(size_)); |
| 113 if (painter_) { |
| 114 DesktopRegion updated_region; |
| 115 if (!painter_->Paint(frame.get(), &updated_region)) { |
| 116 return nullptr; |
| 117 } |
| 118 |
| 119 if (provide_updated_region_hints_) { |
| 120 SetUpdatedRegion(frame.get(), updated_region, enlarge_updated_region_, |
| 121 enlarge_range_, add_random_updated_region_); |
| 122 } else { |
| 123 frame->mutable_updated_region()->SetRect( |
| 124 DesktopRect::MakeSize(frame->size())); |
| 125 } |
| 126 } |
| 127 |
| 128 return frame; |
| 129 } |
| 130 |
| 131 DesktopSize* PainterDesktopFrameGenerator::size() { |
| 132 return &size_; |
| 133 } |
| 134 |
| 135 void PainterDesktopFrameGenerator::set_return_frame(bool return_frame) { |
| 136 return_frame_ = return_frame; |
| 137 } |
| 138 |
| 139 void PainterDesktopFrameGenerator::set_provide_updated_region_hints( |
| 140 bool provide_updated_region_hints) { |
| 141 provide_updated_region_hints_ = provide_updated_region_hints; |
| 142 } |
| 143 |
| 144 void PainterDesktopFrameGenerator::set_enlarge_updated_region( |
| 145 bool enlarge_updated_region) { |
| 146 enlarge_updated_region_ = enlarge_updated_region; |
| 147 } |
| 148 |
| 149 void PainterDesktopFrameGenerator::set_enlarge_range(int enlarge_range) { |
| 150 enlarge_range_ = enlarge_range; |
| 151 } |
| 152 |
| 153 void PainterDesktopFrameGenerator::set_add_random_updated_region( |
| 154 bool add_random_updated_region) { |
| 155 add_random_updated_region_ = add_random_updated_region; |
| 156 } |
| 157 |
| 158 void PainterDesktopFrameGenerator::set_desktop_frame_painter( |
| 159 DesktopFramePainter* painter) { |
| 160 painter_ = painter; |
| 161 } |
| 162 |
| 163 BlackWhiteDesktopFramePainter::BlackWhiteDesktopFramePainter() {} |
| 164 BlackWhiteDesktopFramePainter::~BlackWhiteDesktopFramePainter() {} |
| 165 |
| 166 DesktopRegion* BlackWhiteDesktopFramePainter::updated_region() { |
| 167 return &updated_region_; |
| 168 } |
| 169 |
| 170 bool BlackWhiteDesktopFramePainter::Paint(DesktopFrame* frame, |
| 171 DesktopRegion* updated_region) { |
| 172 RTC_DCHECK(updated_region->is_empty()); |
| 173 memset(frame->data(), 0, frame->stride() * frame->size().height()); |
| 174 PaintRegion(frame, &updated_region_, UINT32_MAX); |
| 175 updated_region_.Swap(updated_region); |
| 176 return true; |
| 177 } |
| 178 |
| 179 } // namespace webrtc |
OLD | NEW |