tor-browser

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

i444_buffer.cc (7604B)


      1 /*
      2 *  Copyright (c) 2021 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 #include "api/video/i444_buffer.h"
     11 
     12 #include <algorithm>
     13 #include <cstdint>
     14 #include <cstring>
     15 #include <utility>
     16 
     17 #include "api/make_ref_counted.h"
     18 #include "api/scoped_refptr.h"
     19 #include "api/video/i420_buffer.h"
     20 #include "api/video/video_frame_buffer.h"
     21 #include "api/video/video_rotation.h"
     22 #include "rtc_base/checks.h"
     23 #include "rtc_base/memory/aligned_malloc.h"
     24 #include "rtc_base/numerics/safe_conversions.h"
     25 #include "third_party/libyuv/include/libyuv/convert.h"
     26 #include "third_party/libyuv/include/libyuv/planar_functions.h"
     27 #include "third_party/libyuv/include/libyuv/rotate.h"
     28 #include "third_party/libyuv/include/libyuv/scale.h"
     29 
     30 // Aligning pointer to 64 bytes for improved performance, e.g. use SIMD.
     31 static const int kBufferAlignment = 64;
     32 
     33 namespace webrtc {
     34 
     35 namespace {
     36 
     37 int I444DataSize(int width,
     38                 int height,
     39                 int stride_y,
     40                 int stride_u,
     41                 int stride_v) {
     42  CheckValidDimensions(width, height, stride_y, stride_u, stride_v);
     43  int64_t h = height, y = stride_y, u = stride_u, v = stride_v;
     44  return checked_cast<int>(y * h + u * h + v * h);
     45 }
     46 
     47 }  // namespace
     48 
     49 I444Buffer::I444Buffer(int width, int height)
     50    : I444Buffer(width, height, width, (width), (width)) {}
     51 
     52 I444Buffer::I444Buffer(int width,
     53                       int height,
     54                       int stride_y,
     55                       int stride_u,
     56                       int stride_v)
     57    : width_(width),
     58      height_(height),
     59      stride_y_(stride_y),
     60      stride_u_(stride_u),
     61      stride_v_(stride_v),
     62      data_(static_cast<uint8_t*>(AlignedMalloc(
     63          I444DataSize(width, height, stride_y, stride_u, stride_v),
     64          kBufferAlignment))) {
     65  RTC_DCHECK_GE(stride_u, width);
     66  RTC_DCHECK_GE(stride_v, width);
     67 }
     68 
     69 I444Buffer::~I444Buffer() {}
     70 
     71 // static
     72 scoped_refptr<I444Buffer> I444Buffer::Create(int width, int height) {
     73  return make_ref_counted<I444Buffer>(width, height);
     74 }
     75 
     76 // static
     77 scoped_refptr<I444Buffer> I444Buffer::Create(int width,
     78                                             int height,
     79                                             int stride_y,
     80                                             int stride_u,
     81                                             int stride_v) {
     82  return make_ref_counted<I444Buffer>(width, height, stride_y, stride_u,
     83                                      stride_v);
     84 }
     85 
     86 // static
     87 scoped_refptr<I444Buffer> I444Buffer::Copy(const I444BufferInterface& source) {
     88  return Copy(source.width(), source.height(), source.DataY(), source.StrideY(),
     89              source.DataU(), source.StrideU(), source.DataV(),
     90              source.StrideV());
     91 }
     92 
     93 // static
     94 scoped_refptr<I444Buffer> I444Buffer::Copy(int width,
     95                                           int height,
     96                                           const uint8_t* data_y,
     97                                           int stride_y,
     98                                           const uint8_t* data_u,
     99                                           int stride_u,
    100                                           const uint8_t* data_v,
    101                                           int stride_v) {
    102  // Note: May use different strides than the input data.
    103  scoped_refptr<I444Buffer> buffer = Create(width, height);
    104  RTC_CHECK_EQ(0, libyuv::I444Copy(data_y, stride_y, data_u, stride_u, data_v,
    105                                   stride_v, buffer->MutableDataY(),
    106                                   buffer->StrideY(), buffer->MutableDataU(),
    107                                   buffer->StrideU(), buffer->MutableDataV(),
    108                                   buffer->StrideV(), width, height));
    109  return buffer;
    110 }
    111 
    112 // static
    113 scoped_refptr<I444Buffer> I444Buffer::Rotate(const I444BufferInterface& src,
    114                                             VideoRotation rotation) {
    115  RTC_CHECK(src.DataY());
    116  RTC_CHECK(src.DataU());
    117  RTC_CHECK(src.DataV());
    118 
    119  int rotated_width = src.width();
    120  int rotated_height = src.height();
    121  if (rotation == kVideoRotation_90 || rotation == kVideoRotation_270) {
    122    std::swap(rotated_width, rotated_height);
    123  }
    124 
    125  scoped_refptr<I444Buffer> buffer =
    126      I444Buffer::Create(rotated_width, rotated_height);
    127 
    128  RTC_CHECK_EQ(0,
    129               libyuv::I444Rotate(
    130                   src.DataY(), src.StrideY(), src.DataU(), src.StrideU(),
    131                   src.DataV(), src.StrideV(), buffer->MutableDataY(),
    132                   buffer->StrideY(), buffer->MutableDataU(), buffer->StrideU(),
    133                   buffer->MutableDataV(), buffer->StrideV(), src.width(),
    134                   src.height(), static_cast<libyuv::RotationMode>(rotation)));
    135 
    136  return buffer;
    137 }
    138 
    139 scoped_refptr<I420BufferInterface> I444Buffer::ToI420() {
    140  scoped_refptr<I420Buffer> i420_buffer = I420Buffer::Create(width(), height());
    141  libyuv::I444ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(),
    142                     i420_buffer->MutableDataY(), i420_buffer->StrideY(),
    143                     i420_buffer->MutableDataU(), i420_buffer->StrideU(),
    144                     i420_buffer->MutableDataV(), i420_buffer->StrideV(),
    145                     width(), height());
    146  return i420_buffer;
    147 }
    148 
    149 void I444Buffer::InitializeData() {
    150  memset(data_.get(), 0,
    151         I444DataSize(width_, height_, stride_y_, stride_u_, stride_v_));
    152 }
    153 
    154 int I444Buffer::width() const {
    155  return width_;
    156 }
    157 
    158 int I444Buffer::height() const {
    159  return height_;
    160 }
    161 
    162 const uint8_t* I444Buffer::DataY() const {
    163  return data_.get();
    164 }
    165 const uint8_t* I444Buffer::DataU() const {
    166  return data_.get() + stride_y_ * height_;
    167 }
    168 const uint8_t* I444Buffer::DataV() const {
    169  return data_.get() + stride_y_ * height_ + stride_u_ * ((height_));
    170 }
    171 
    172 int I444Buffer::StrideY() const {
    173  return stride_y_;
    174 }
    175 int I444Buffer::StrideU() const {
    176  return stride_u_;
    177 }
    178 int I444Buffer::StrideV() const {
    179  return stride_v_;
    180 }
    181 
    182 uint8_t* I444Buffer::MutableDataY() {
    183  return const_cast<uint8_t*>(DataY());
    184 }
    185 uint8_t* I444Buffer::MutableDataU() {
    186  return const_cast<uint8_t*>(DataU());
    187 }
    188 uint8_t* I444Buffer::MutableDataV() {
    189  return const_cast<uint8_t*>(DataV());
    190 }
    191 
    192 void I444Buffer::CropAndScaleFrom(const I444BufferInterface& src,
    193                                  int offset_x,
    194                                  int offset_y,
    195                                  int crop_width,
    196                                  int crop_height) {
    197  RTC_CHECK_LE(crop_width, src.width());
    198  RTC_CHECK_LE(crop_height, src.height());
    199  RTC_CHECK_LE(crop_width + offset_x, src.width());
    200  RTC_CHECK_LE(crop_height + offset_y, src.height());
    201  RTC_CHECK_GE(offset_x, 0);
    202  RTC_CHECK_GE(offset_y, 0);
    203 
    204  const uint8_t* y_plane = src.DataY() + src.StrideY() * offset_y + offset_x;
    205  const uint8_t* u_plane = src.DataU() + src.StrideU() * offset_y + offset_x;
    206  const uint8_t* v_plane = src.DataV() + src.StrideV() * offset_y + offset_x;
    207  int res =
    208      libyuv::I444Scale(y_plane, src.StrideY(), u_plane, src.StrideU(), v_plane,
    209                        src.StrideV(), crop_width, crop_height, MutableDataY(),
    210                        StrideY(), MutableDataU(), StrideU(), MutableDataV(),
    211                        StrideV(), width(), height(), libyuv::kFilterBox);
    212 
    213  RTC_DCHECK_EQ(res, 0);
    214 }
    215 
    216 }  // namespace webrtc