tor-browser

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

desktop_frame.cc (9143B)


      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 "modules/desktop_capture/desktop_frame.h"
     12 
     13 #include <algorithm>
     14 #include <cmath>
     15 #include <cstdint>
     16 #include <cstring>
     17 #include <memory>
     18 #include <utility>
     19 
     20 #include "modules/desktop_capture/desktop_capture_types.h"
     21 #include "modules/desktop_capture/desktop_geometry.h"
     22 #include "modules/desktop_capture/shared_memory.h"
     23 #include "rtc_base/checks.h"
     24 #include "third_party/libyuv/include/libyuv/planar_functions.h"
     25 
     26 namespace webrtc {
     27 
     28 DesktopFrame::DesktopFrame(DesktopSize size,
     29                           int stride,
     30                           FourCC pixel_format,
     31                           uint8_t* data,
     32                           SharedMemory* shared_memory)
     33    : data_(data),
     34      shared_memory_(shared_memory),
     35      size_(size),
     36      stride_(stride),
     37      pixel_format_(pixel_format),
     38      capture_time_ms_(0),
     39      capturer_id_(DesktopCapturerId::kUnknown) {
     40  RTC_DCHECK(size_.width() >= 0);
     41  RTC_DCHECK(size_.height() >= 0);
     42 }
     43 
     44 DesktopFrame::DesktopFrame(DesktopSize size,
     45                           int stride,
     46                           uint8_t* data,
     47                           SharedMemory* shared_memory)
     48    : DesktopFrame(size, stride, FOURCC_ARGB, data, shared_memory) {}
     49 
     50 DesktopFrame::~DesktopFrame() = default;
     51 
     52 void DesktopFrame::CopyPixelsFrom(const uint8_t* src_buffer,
     53                                  int src_stride,
     54                                  const DesktopRect& dest_rect) {
     55  RTC_CHECK(DesktopRect::MakeSize(size()).ContainsRect(dest_rect));
     56 
     57  uint8_t* dest = GetFrameDataAtPos(dest_rect.top_left());
     58  libyuv::CopyPlane(src_buffer, src_stride, dest, stride(),
     59                    DesktopFrame::kBytesPerPixel * dest_rect.width(),
     60                    dest_rect.height());
     61 }
     62 
     63 void DesktopFrame::CopyPixelsFrom(const DesktopFrame& src_frame,
     64                                  const DesktopVector& src_pos,
     65                                  const DesktopRect& dest_rect) {
     66  RTC_CHECK(DesktopRect::MakeSize(src_frame.size())
     67                .ContainsRect(
     68                    DesktopRect::MakeOriginSize(src_pos, dest_rect.size())));
     69  RTC_CHECK_EQ(pixel_format(), src_frame.pixel_format());
     70 
     71  CopyPixelsFrom(src_frame.GetFrameDataAtPos(src_pos), src_frame.stride(),
     72                 dest_rect);
     73 }
     74 
     75 bool DesktopFrame::CopyIntersectingPixelsFrom(const DesktopFrame& src_frame,
     76                                              double horizontal_scale,
     77                                              double vertical_scale) {
     78  const DesktopVector& origin = top_left();
     79  const DesktopVector& src_frame_origin = src_frame.top_left();
     80 
     81  DesktopVector src_frame_offset = src_frame_origin.subtract(origin);
     82 
     83  // Determine the intersection, first adjusting its origin to account for any
     84  // DPI scaling.
     85  DesktopRect intersection_rect = src_frame.rect();
     86  if (horizontal_scale != 1.0 || vertical_scale != 1.0) {
     87    DesktopVector origin_adjustment(
     88        static_cast<int>(
     89            std::round((horizontal_scale - 1.0) * src_frame_offset.x())),
     90        static_cast<int>(
     91            std::round((vertical_scale - 1.0) * src_frame_offset.y())));
     92 
     93    intersection_rect.Translate(origin_adjustment);
     94 
     95    src_frame_offset = src_frame_offset.add(origin_adjustment);
     96  }
     97 
     98  intersection_rect.IntersectWith(rect());
     99  if (intersection_rect.is_empty()) {
    100    return false;
    101  }
    102 
    103  // Translate the intersection rect to be relative to the outer rect.
    104  intersection_rect.Translate(-origin.x(), -origin.y());
    105 
    106  // Determine source position for the copy (offsets of outer frame from
    107  // source origin, if positive).
    108  int32_t src_pos_x = std::max(0, -src_frame_offset.x());
    109  int32_t src_pos_y = std::max(0, -src_frame_offset.y());
    110 
    111  CopyPixelsFrom(src_frame, DesktopVector(src_pos_x, src_pos_y),
    112                 intersection_rect);
    113  return true;
    114 }
    115 
    116 DesktopRect DesktopFrame::rect() const {
    117  const float scale = scale_factor();
    118  // Only scale the size.
    119  return DesktopRect::MakeXYWH(top_left().x(), top_left().y(),
    120                               size().width() / scale, size().height() / scale);
    121 }
    122 
    123 float DesktopFrame::scale_factor() const {
    124  float scale = 1.0f;
    125 
    126 #if defined(WEBRTC_MAC) || defined(CHROMEOS)
    127  // At least on Windows the logical and physical pixel are the same
    128  // See http://crbug.com/948362.
    129  if (!dpi().is_zero() && dpi().x() == dpi().y())
    130    scale = dpi().x() / kStandardDPI;
    131 #endif
    132 
    133  return scale;
    134 }
    135 
    136 uint8_t* DesktopFrame::GetFrameDataAtPos(const DesktopVector& pos) const {
    137  return data() + stride() * pos.y() + DesktopFrame::kBytesPerPixel * pos.x();
    138 }
    139 
    140 void DesktopFrame::CopyFrameInfoFrom(const DesktopFrame& other) {
    141  set_dpi(other.dpi());
    142  set_capture_time_ms(other.capture_time_ms());
    143  set_capturer_id(other.capturer_id());
    144  *mutable_updated_region() = other.updated_region();
    145  set_top_left(other.top_left());
    146  set_icc_profile(other.icc_profile());
    147  set_may_contain_cursor(other.may_contain_cursor());
    148  set_device_scale_factor(other.device_scale_factor());
    149 }
    150 
    151 void DesktopFrame::MoveFrameInfoFrom(DesktopFrame* other) {
    152  set_dpi(other->dpi());
    153  set_capture_time_ms(other->capture_time_ms());
    154  set_capturer_id(other->capturer_id());
    155  mutable_updated_region()->Swap(other->mutable_updated_region());
    156  set_top_left(other->top_left());
    157  set_icc_profile(other->icc_profile());
    158  set_may_contain_cursor(other->may_contain_cursor());
    159  set_device_scale_factor(other->device_scale_factor());
    160 }
    161 
    162 bool DesktopFrame::FrameDataIsBlack() const {
    163  if (size().is_empty())
    164    return false;
    165 
    166  uint32_t* pixel = reinterpret_cast<uint32_t*>(data());
    167  for (int i = 0; i < size().width() * size().height(); ++i) {
    168    if (*pixel++)
    169      return false;
    170  }
    171  return true;
    172 }
    173 
    174 void DesktopFrame::SetFrameDataToBlack() {
    175  const uint8_t kBlackPixelValue = 0x00;
    176  memset(data(), kBlackPixelValue, stride() * size().height());
    177 }
    178 
    179 BasicDesktopFrame::BasicDesktopFrame(DesktopSize size)
    180    : BasicDesktopFrame(size, FOURCC_ARGB) {}
    181 
    182 BasicDesktopFrame::BasicDesktopFrame(DesktopSize size, FourCC pixel_format)
    183    : DesktopFrame(size,
    184                   kBytesPerPixel * size.width(),
    185                   pixel_format,
    186                   new uint8_t[kBytesPerPixel * size.width() * size.height()](),
    187                   nullptr) {}
    188 
    189 BasicDesktopFrame::~BasicDesktopFrame() {
    190  delete[] data_;
    191 }
    192 
    193 // static
    194 DesktopFrame* BasicDesktopFrame::CopyOf(const DesktopFrame& frame) {
    195  DesktopFrame* result =
    196      new BasicDesktopFrame(frame.size(), frame.pixel_format());
    197  // TODO(crbug.com/1330019): Temporary workaround for a known libyuv crash when
    198  // the height or width is 0. Remove this once this change has been merged.
    199  if (frame.size().width() && frame.size().height()) {
    200    libyuv::CopyPlane(frame.data(), frame.stride(), result->data(),
    201                      result->stride(), frame.size().width() * kBytesPerPixel,
    202                      frame.size().height());
    203  }
    204  result->CopyFrameInfoFrom(frame);
    205  return result;
    206 }
    207 
    208 // static
    209 std::unique_ptr<DesktopFrame> SharedMemoryDesktopFrame::Create(
    210    DesktopSize size,
    211    FourCC pixel_format,
    212    SharedMemoryFactory* shared_memory_factory) {
    213  RTC_DCHECK(shared_memory_factory);
    214 
    215  size_t buffer_size = size.height() * size.width() * kBytesPerPixel;
    216  std::unique_ptr<SharedMemory> shared_memory =
    217      shared_memory_factory->CreateSharedMemory(buffer_size);
    218  if (!shared_memory)
    219    return nullptr;
    220 
    221  return std::make_unique<SharedMemoryDesktopFrame>(
    222      size, size.width() * kBytesPerPixel, pixel_format,
    223      std::move(shared_memory));
    224 }
    225 
    226 SharedMemoryDesktopFrame::SharedMemoryDesktopFrame(
    227    DesktopSize size,
    228    int stride,
    229    std::unique_ptr<SharedMemory> shared_memory)
    230    : SharedMemoryDesktopFrame(size,
    231                               stride,
    232                               FOURCC_ARGB,
    233                               std::move(shared_memory)) {}
    234 
    235 SharedMemoryDesktopFrame::SharedMemoryDesktopFrame(DesktopSize size,
    236                                                   int stride,
    237                                                   FourCC pixel_format,
    238                                                   SharedMemory* shared_memory)
    239    : DesktopFrame(size,
    240                   stride,
    241                   pixel_format,
    242                   reinterpret_cast<uint8_t*>(shared_memory->data()),
    243                   shared_memory) {}
    244 
    245 SharedMemoryDesktopFrame::SharedMemoryDesktopFrame(
    246    DesktopSize size,
    247    int stride,
    248    FourCC pixel_format,
    249    std::unique_ptr<SharedMemory> shared_memory)
    250    : SharedMemoryDesktopFrame(size,
    251                               stride,
    252                               pixel_format,
    253                               shared_memory.release()) {}
    254 
    255 SharedMemoryDesktopFrame::~SharedMemoryDesktopFrame() {
    256  delete shared_memory_;
    257 }
    258 
    259 }  // namespace webrtc