tor-browser

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

video_frame.cc (8846B)


      1 /*
      2 *  Copyright (c) 2012 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 "api/video/video_frame.h"
     12 
     13 #include <algorithm>
     14 #include <cstdint>
     15 #include <optional>
     16 #include <utility>
     17 
     18 #include "api/rtp_packet_infos.h"
     19 #include "api/scoped_refptr.h"
     20 #include "api/units/timestamp.h"
     21 #include "api/video/color_space.h"
     22 #include "api/video/video_frame_buffer.h"
     23 #include "api/video/video_rotation.h"
     24 #include "rtc_base/checks.h"
     25 #include "rtc_base/time_utils.h"
     26 
     27 namespace webrtc {
     28 
     29 void VideoFrame::UpdateRect::Union(const UpdateRect& other) {
     30  if (other.IsEmpty())
     31    return;
     32  if (IsEmpty()) {
     33    *this = other;
     34    return;
     35  }
     36  int right = std::max(offset_x + width, other.offset_x + other.width);
     37  int bottom = std::max(offset_y + height, other.offset_y + other.height);
     38  offset_x = std::min(offset_x, other.offset_x);
     39  offset_y = std::min(offset_y, other.offset_y);
     40  width = right - offset_x;
     41  height = bottom - offset_y;
     42  RTC_DCHECK_GT(width, 0);
     43  RTC_DCHECK_GT(height, 0);
     44 }
     45 
     46 void VideoFrame::UpdateRect::Intersect(const UpdateRect& other) {
     47  if (other.IsEmpty() || IsEmpty()) {
     48    MakeEmptyUpdate();
     49    return;
     50  }
     51 
     52  int right = std::min(offset_x + width, other.offset_x + other.width);
     53  int bottom = std::min(offset_y + height, other.offset_y + other.height);
     54  offset_x = std::max(offset_x, other.offset_x);
     55  offset_y = std::max(offset_y, other.offset_y);
     56  width = right - offset_x;
     57  height = bottom - offset_y;
     58  if (width <= 0 || height <= 0) {
     59    MakeEmptyUpdate();
     60  }
     61 }
     62 
     63 void VideoFrame::UpdateRect::MakeEmptyUpdate() {
     64  width = height = offset_x = offset_y = 0;
     65 }
     66 
     67 bool VideoFrame::UpdateRect::IsEmpty() const {
     68  return width == 0 && height == 0;
     69 }
     70 
     71 VideoFrame::UpdateRect VideoFrame::UpdateRect::ScaleWithFrame(
     72    int frame_width,
     73    int frame_height,
     74    int crop_x,
     75    int crop_y,
     76    int crop_width,
     77    int crop_height,
     78    int scaled_width,
     79    int scaled_height) const {
     80  RTC_DCHECK_GT(frame_width, 0);
     81  RTC_DCHECK_GT(frame_height, 0);
     82 
     83  RTC_DCHECK_GT(crop_width, 0);
     84  RTC_DCHECK_GT(crop_height, 0);
     85 
     86  RTC_DCHECK_LE(crop_width + crop_x, frame_width);
     87  RTC_DCHECK_LE(crop_height + crop_y, frame_height);
     88 
     89  RTC_DCHECK_GT(scaled_width, 0);
     90  RTC_DCHECK_GT(scaled_height, 0);
     91 
     92  // Check if update rect is out of the cropped area.
     93  if (offset_x + width < crop_x || offset_x > crop_x + crop_width ||
     94      offset_y + height < crop_y || offset_y > crop_y + crop_width) {
     95    return {.offset_x = 0, .offset_y = 0, .width = 0, .height = 0};
     96  }
     97 
     98  int x = offset_x - crop_x;
     99  int w = width;
    100  if (x < 0) {
    101    w += x;
    102    x = 0;
    103  }
    104  int y = offset_y - crop_y;
    105  int h = height;
    106  if (y < 0) {
    107    h += y;
    108    y = 0;
    109  }
    110 
    111  // Lower corner is rounded down.
    112  x = x * scaled_width / crop_width;
    113  y = y * scaled_height / crop_height;
    114  // Upper corner is rounded up.
    115  w = (w * scaled_width + crop_width - 1) / crop_width;
    116  h = (h * scaled_height + crop_height - 1) / crop_height;
    117 
    118  // Round to full 2x2 blocks due to possible subsampling in the pixel data.
    119  if (x % 2) {
    120    --x;
    121    ++w;
    122  }
    123  if (y % 2) {
    124    --y;
    125    ++h;
    126  }
    127  if (w % 2) {
    128    ++w;
    129  }
    130  if (h % 2) {
    131    ++h;
    132  }
    133 
    134  // Expand the update rect by 2 pixels in each direction to include any
    135  // possible scaling artifacts.
    136  if (scaled_width != crop_width || scaled_height != crop_height) {
    137    if (x > 0) {
    138      x -= 2;
    139      w += 2;
    140    }
    141    if (y > 0) {
    142      y -= 2;
    143      h += 2;
    144    }
    145    w += 2;
    146    h += 2;
    147  }
    148 
    149  // Ensure update rect is inside frame dimensions.
    150  if (x + w > scaled_width) {
    151    w = scaled_width - x;
    152  }
    153  if (y + h > scaled_height) {
    154    h = scaled_height - y;
    155  }
    156  RTC_DCHECK_GE(w, 0);
    157  RTC_DCHECK_GE(h, 0);
    158  if (w == 0 || h == 0) {
    159    w = 0;
    160    h = 0;
    161    x = 0;
    162    y = 0;
    163  }
    164 
    165  return {.offset_x = x, .offset_y = y, .width = w, .height = h};
    166 }
    167 
    168 VideoFrame::Builder::Builder() = default;
    169 
    170 VideoFrame::Builder::~Builder() = default;
    171 
    172 VideoFrame VideoFrame::Builder::build() {
    173  RTC_CHECK(video_frame_buffer_ != nullptr);
    174  return VideoFrame(id_, video_frame_buffer_, timestamp_us_,
    175                    presentation_timestamp_, reference_time_, timestamp_rtp_,
    176                    ntp_time_ms_, rotation_, color_space_, render_parameters_,
    177                    update_rect_, packet_infos_, is_repeat_frame_);
    178 }
    179 
    180 VideoFrame::Builder& VideoFrame::Builder::set_video_frame_buffer(
    181    const scoped_refptr<VideoFrameBuffer>& buffer) {
    182  video_frame_buffer_ = buffer;
    183  return *this;
    184 }
    185 
    186 VideoFrame::Builder& VideoFrame::Builder::set_timestamp_ms(
    187    int64_t timestamp_ms) {
    188  timestamp_us_ = timestamp_ms * kNumMicrosecsPerMillisec;
    189  return *this;
    190 }
    191 
    192 VideoFrame::Builder& VideoFrame::Builder::set_timestamp_us(
    193    int64_t timestamp_us) {
    194  timestamp_us_ = timestamp_us;
    195  return *this;
    196 }
    197 
    198 VideoFrame::Builder& VideoFrame::Builder::set_capture_time_identifier(
    199    const std::optional<Timestamp>& presentation_timestamp) {
    200  presentation_timestamp_ = presentation_timestamp;
    201  return *this;
    202 }
    203 
    204 VideoFrame::Builder& VideoFrame::Builder::set_presentation_timestamp(
    205    const std::optional<Timestamp>& presentation_timestamp) {
    206  presentation_timestamp_ = presentation_timestamp;
    207  return *this;
    208 }
    209 
    210 VideoFrame::Builder& VideoFrame::Builder::set_reference_time(
    211    const std::optional<Timestamp>& reference_time) {
    212  reference_time_ = reference_time;
    213  return *this;
    214 }
    215 
    216 VideoFrame::Builder& VideoFrame::Builder::set_rtp_timestamp(
    217    uint32_t rtp_timestamp) {
    218  timestamp_rtp_ = rtp_timestamp;
    219  return *this;
    220 }
    221 
    222 VideoFrame::Builder& VideoFrame::Builder::set_timestamp_rtp(
    223    uint32_t timestamp_rtp) {
    224  timestamp_rtp_ = timestamp_rtp;
    225  return *this;
    226 }
    227 
    228 VideoFrame::Builder& VideoFrame::Builder::set_ntp_time_ms(int64_t ntp_time_ms) {
    229  ntp_time_ms_ = ntp_time_ms;
    230  return *this;
    231 }
    232 
    233 VideoFrame::Builder& VideoFrame::Builder::set_rotation(VideoRotation rotation) {
    234  rotation_ = rotation;
    235  return *this;
    236 }
    237 
    238 VideoFrame::Builder& VideoFrame::Builder::set_color_space(
    239    const std::optional<ColorSpace>& color_space) {
    240  color_space_ = color_space;
    241  return *this;
    242 }
    243 
    244 VideoFrame::Builder& VideoFrame::Builder::set_color_space(
    245    const ColorSpace* color_space) {
    246  color_space_ = color_space ? std::make_optional(*color_space) : std::nullopt;
    247  return *this;
    248 }
    249 
    250 VideoFrame::Builder& VideoFrame::Builder::set_id(uint16_t id) {
    251  id_ = id;
    252  return *this;
    253 }
    254 
    255 VideoFrame::Builder& VideoFrame::Builder::set_update_rect(
    256    const std::optional<VideoFrame::UpdateRect>& update_rect) {
    257  update_rect_ = update_rect;
    258  return *this;
    259 }
    260 
    261 VideoFrame::Builder& VideoFrame::Builder::set_packet_infos(
    262    RtpPacketInfos packet_infos) {
    263  packet_infos_ = std::move(packet_infos);
    264  return *this;
    265 }
    266 
    267 VideoFrame::Builder& VideoFrame::Builder::set_is_repeat_frame(
    268    bool is_repeat_frame) {
    269  is_repeat_frame_ = is_repeat_frame;
    270  return *this;
    271 }
    272 
    273 VideoFrame::VideoFrame(const scoped_refptr<VideoFrameBuffer>& buffer,
    274                       VideoRotation rotation,
    275                       int64_t timestamp_us)
    276    : video_frame_buffer_(buffer),
    277      timestamp_rtp_(0),
    278      ntp_time_ms_(0),
    279      timestamp_us_(timestamp_us),
    280      rotation_(rotation),
    281      is_repeat_frame_(false) {}
    282 
    283 VideoFrame::VideoFrame(const scoped_refptr<VideoFrameBuffer>& buffer,
    284                       uint32_t timestamp_rtp,
    285                       int64_t render_time_ms,
    286                       VideoRotation rotation)
    287    : video_frame_buffer_(buffer),
    288      timestamp_rtp_(timestamp_rtp),
    289      ntp_time_ms_(0),
    290      timestamp_us_(render_time_ms * kNumMicrosecsPerMillisec),
    291      rotation_(rotation),
    292      is_repeat_frame_(false) {
    293  RTC_DCHECK(buffer);
    294 }
    295 
    296 VideoFrame::~VideoFrame() = default;
    297 
    298 VideoFrame::VideoFrame(const VideoFrame&) = default;
    299 VideoFrame::VideoFrame(VideoFrame&&) = default;
    300 VideoFrame& VideoFrame::operator=(const VideoFrame&) = default;
    301 VideoFrame& VideoFrame::operator=(VideoFrame&&) = default;
    302 
    303 int VideoFrame::width() const {
    304  return video_frame_buffer_ ? video_frame_buffer_->width() : 0;
    305 }
    306 
    307 int VideoFrame::height() const {
    308  return video_frame_buffer_ ? video_frame_buffer_->height() : 0;
    309 }
    310 
    311 uint32_t VideoFrame::size() const {
    312  return width() * height();
    313 }
    314 
    315 scoped_refptr<VideoFrameBuffer> VideoFrame::video_frame_buffer() const {
    316  return video_frame_buffer_;
    317 }
    318 
    319 void VideoFrame::set_video_frame_buffer(
    320    const scoped_refptr<VideoFrameBuffer>& buffer) {
    321  RTC_CHECK(buffer);
    322  video_frame_buffer_ = buffer;
    323 }
    324 
    325 int64_t VideoFrame::render_time_ms() const {
    326  return timestamp_us() / kNumMicrosecsPerMillisec;
    327 }
    328 
    329 }  // namespace webrtc