blob: 7a71f43493a619afac42dee376af1c283f64fb12 [file] [log] [blame]
nisseaf916892017-01-10 07:44:26 -08001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "api/video/video_frame.h"
nisseaf916892017-01-10 07:44:26 -080012
Ilya Nikolaevskiy71aee3a2019-02-18 13:01:26 +010013#include <algorithm>
14
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 09:11:00 -080016#include "rtc_base/time_utils.h"
nisseaf916892017-01-10 07:44:26 -080017
18namespace webrtc {
19
Ilya Nikolaevskiy71aee3a2019-02-18 13:01:26 +010020void VideoFrame::UpdateRect::Union(const UpdateRect& other) {
21 if (other.IsEmpty())
22 return;
23 if (IsEmpty()) {
24 *this = other;
25 return;
26 }
27 int right = std::max(offset_x + width, other.offset_x + other.width);
28 int bottom = std::max(offset_y + height, other.offset_y + other.height);
29 offset_x = std::min(offset_x, other.offset_x);
30 offset_y = std::min(offset_y, other.offset_y);
31 width = right - offset_x;
32 height = bottom - offset_y;
33 RTC_DCHECK_GT(width, 0);
34 RTC_DCHECK_GT(height, 0);
35}
36
37void VideoFrame::UpdateRect::Intersect(const UpdateRect& other) {
38 if (other.IsEmpty() || IsEmpty()) {
39 MakeEmptyUpdate();
40 return;
41 }
42
43 int right = std::min(offset_x + width, other.offset_x + other.width);
44 int bottom = std::min(offset_y + height, other.offset_y + other.height);
45 offset_x = std::max(offset_x, other.offset_x);
46 offset_y = std::max(offset_y, other.offset_y);
47 width = right - offset_x;
48 height = bottom - offset_y;
49 if (width <= 0 || height <= 0) {
50 MakeEmptyUpdate();
51 }
52}
53
54void VideoFrame::UpdateRect::MakeEmptyUpdate() {
55 width = height = offset_x = offset_y = 0;
56}
57
58bool VideoFrame::UpdateRect::IsEmpty() const {
59 return width == 0 && height == 0;
60}
61
Emircan Uysaler800787f2018-07-16 10:01:49 -070062VideoFrame::Builder::Builder() = default;
63
64VideoFrame::Builder::~Builder() = default;
65
66VideoFrame VideoFrame::Builder::build() {
Ilya Nikolaevskiy6aca0b72019-02-13 11:55:57 +010067 RTC_CHECK(video_frame_buffer_ != nullptr);
Artem Titov1ebfb6a2019-01-03 23:49:37 +010068 return VideoFrame(id_, video_frame_buffer_, timestamp_us_, timestamp_rtp_,
Ilya Nikolaevskiy6aca0b72019-02-13 11:55:57 +010069 ntp_time_ms_, rotation_, color_space_, update_rect_);
Emircan Uysaler800787f2018-07-16 10:01:49 -070070}
71
72VideoFrame::Builder& VideoFrame::Builder::set_video_frame_buffer(
73 const rtc::scoped_refptr<VideoFrameBuffer>& buffer) {
74 video_frame_buffer_ = buffer;
75 return *this;
76}
77
78VideoFrame::Builder& VideoFrame::Builder::set_timestamp_ms(
79 int64_t timestamp_ms) {
80 timestamp_us_ = timestamp_ms * rtc::kNumMicrosecsPerMillisec;
81 return *this;
82}
83
84VideoFrame::Builder& VideoFrame::Builder::set_timestamp_us(
85 int64_t timestamp_us) {
86 timestamp_us_ = timestamp_us;
87 return *this;
88}
89
90VideoFrame::Builder& VideoFrame::Builder::set_timestamp_rtp(
91 uint32_t timestamp_rtp) {
92 timestamp_rtp_ = timestamp_rtp;
93 return *this;
94}
95
96VideoFrame::Builder& VideoFrame::Builder::set_ntp_time_ms(int64_t ntp_time_ms) {
97 ntp_time_ms_ = ntp_time_ms;
98 return *this;
99}
100
101VideoFrame::Builder& VideoFrame::Builder::set_rotation(VideoRotation rotation) {
102 rotation_ = rotation;
103 return *this;
104}
105
106VideoFrame::Builder& VideoFrame::Builder::set_color_space(
Danil Chapovalovb7698942019-02-05 11:32:19 +0100107 const absl::optional<ColorSpace>& color_space) {
Emircan Uysaler800787f2018-07-16 10:01:49 -0700108 color_space_ = color_space;
109 return *this;
110}
111
Johannes Kron4749e4e2018-11-21 10:18:18 +0100112VideoFrame::Builder& VideoFrame::Builder::set_color_space(
113 const ColorSpace* color_space) {
114 color_space_ =
115 color_space ? absl::make_optional(*color_space) : absl::nullopt;
Johannes Kronfbf16832018-11-05 16:13:02 +0100116 return *this;
117}
118
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100119VideoFrame::Builder& VideoFrame::Builder::set_id(uint16_t id) {
120 id_ = id;
121 return *this;
122}
123
Ilya Nikolaevskiy6aca0b72019-02-13 11:55:57 +0100124VideoFrame::Builder& VideoFrame::Builder::set_update_rect(
125 const VideoFrame::UpdateRect& update_rect) {
126 update_rect_ = update_rect;
127 return *this;
128}
129
nisseaf916892017-01-10 07:44:26 -0800130VideoFrame::VideoFrame(const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
131 webrtc::VideoRotation rotation,
132 int64_t timestamp_us)
133 : video_frame_buffer_(buffer),
134 timestamp_rtp_(0),
135 ntp_time_ms_(0),
136 timestamp_us_(timestamp_us),
Ilya Nikolaevskiy6aca0b72019-02-13 11:55:57 +0100137 rotation_(rotation),
138 update_rect_{0, 0, buffer->width(), buffer->height()} {}
nisseaf916892017-01-10 07:44:26 -0800139
140VideoFrame::VideoFrame(const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
Niels Möller2ac64462018-06-11 11:14:32 +0200141 uint32_t timestamp_rtp,
nisseaf916892017-01-10 07:44:26 -0800142 int64_t render_time_ms,
143 VideoRotation rotation)
144 : video_frame_buffer_(buffer),
Niels Möller2ac64462018-06-11 11:14:32 +0200145 timestamp_rtp_(timestamp_rtp),
nisseaf916892017-01-10 07:44:26 -0800146 ntp_time_ms_(0),
147 timestamp_us_(render_time_ms * rtc::kNumMicrosecsPerMillisec),
Ilya Nikolaevskiy6aca0b72019-02-13 11:55:57 +0100148 rotation_(rotation),
149 update_rect_{0, 0, buffer->width(), buffer->height()} {
nisseaf916892017-01-10 07:44:26 -0800150 RTC_DCHECK(buffer);
151}
152
Ilya Nikolaevskiy871e1442019-02-11 13:35:03 +0100153VideoFrame::VideoFrame(uint16_t id,
154 const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
155 int64_t timestamp_us,
156 uint32_t timestamp_rtp,
157 int64_t ntp_time_ms,
158 VideoRotation rotation,
Ilya Nikolaevskiy6aca0b72019-02-13 11:55:57 +0100159 const absl::optional<ColorSpace>& color_space,
160 const absl::optional<UpdateRect>& update_rect)
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100161 : id_(id),
162 video_frame_buffer_(buffer),
Emircan Uysaler800787f2018-07-16 10:01:49 -0700163 timestamp_rtp_(timestamp_rtp),
164 ntp_time_ms_(ntp_time_ms),
165 timestamp_us_(timestamp_us),
166 rotation_(rotation),
Ilya Nikolaevskiy6aca0b72019-02-13 11:55:57 +0100167 color_space_(color_space),
168 update_rect_(update_rect.value_or(UpdateRect{
169 0, 0, video_frame_buffer_->width(), video_frame_buffer_->height()})) {
170 RTC_DCHECK_GE(update_rect_.offset_x, 0);
171 RTC_DCHECK_GE(update_rect_.offset_y, 0);
172 RTC_DCHECK_LE(update_rect_.offset_x + update_rect_.width, width());
173 RTC_DCHECK_LE(update_rect_.offset_y + update_rect_.height, height());
174}
Emircan Uysaler800787f2018-07-16 10:01:49 -0700175
nisseaf916892017-01-10 07:44:26 -0800176VideoFrame::~VideoFrame() = default;
177
178VideoFrame::VideoFrame(const VideoFrame&) = default;
179VideoFrame::VideoFrame(VideoFrame&&) = default;
180VideoFrame& VideoFrame::operator=(const VideoFrame&) = default;
181VideoFrame& VideoFrame::operator=(VideoFrame&&) = default;
182
183int VideoFrame::width() const {
184 return video_frame_buffer_ ? video_frame_buffer_->width() : 0;
185}
186
187int VideoFrame::height() const {
188 return video_frame_buffer_ ? video_frame_buffer_->height() : 0;
189}
190
kthelgason2bc68642017-02-07 07:02:22 -0800191uint32_t VideoFrame::size() const {
192 return width() * height();
193}
194
nisseaf916892017-01-10 07:44:26 -0800195rtc::scoped_refptr<VideoFrameBuffer> VideoFrame::video_frame_buffer() const {
196 return video_frame_buffer_;
197}
198
nisseaf916892017-01-10 07:44:26 -0800199int64_t VideoFrame::render_time_ms() const {
200 return timestamp_us() / rtc::kNumMicrosecsPerMillisec;
201}
202
203} // namespace webrtc