tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

desktop_frame_generator.cc (6693B)


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