blob: 63902af3d58e39854e72f9c507e97d7cb36c3987 [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>
Chen Xingf00bf422019-06-20 10:05:55 +020014#include <utility>
Ilya Nikolaevskiy71aee3a2019-02-18 13:01:26 +010015
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 09:11:00 -080017#include "rtc_base/time_utils.h"
nisseaf916892017-01-10 07:44:26 -080018
19namespace webrtc {
20
Ilya Nikolaevskiy71aee3a2019-02-18 13:01:26 +010021void VideoFrame::UpdateRect::Union(const UpdateRect& other) {
22 if (other.IsEmpty())
23 return;
24 if (IsEmpty()) {
25 *this = other;
26 return;
27 }
28 int right = std::max(offset_x + width, other.offset_x + other.width);
29 int bottom = std::max(offset_y + height, other.offset_y + other.height);
30 offset_x = std::min(offset_x, other.offset_x);
31 offset_y = std::min(offset_y, other.offset_y);
32 width = right - offset_x;
33 height = bottom - offset_y;
34 RTC_DCHECK_GT(width, 0);
35 RTC_DCHECK_GT(height, 0);
36}
37
38void VideoFrame::UpdateRect::Intersect(const UpdateRect& other) {
39 if (other.IsEmpty() || IsEmpty()) {
40 MakeEmptyUpdate();
41 return;
42 }
43
44 int right = std::min(offset_x + width, other.offset_x + other.width);
45 int bottom = std::min(offset_y + height, other.offset_y + other.height);
46 offset_x = std::max(offset_x, other.offset_x);
47 offset_y = std::max(offset_y, other.offset_y);
48 width = right - offset_x;
49 height = bottom - offset_y;
50 if (width <= 0 || height <= 0) {
51 MakeEmptyUpdate();
52 }
53}
54
55void VideoFrame::UpdateRect::MakeEmptyUpdate() {
56 width = height = offset_x = offset_y = 0;
57}
58
59bool VideoFrame::UpdateRect::IsEmpty() const {
60 return width == 0 && height == 0;
61}
62
Emircan Uysaler800787f2018-07-16 10:01:49 -070063VideoFrame::Builder::Builder() = default;
64
65VideoFrame::Builder::~Builder() = default;
66
67VideoFrame VideoFrame::Builder::build() {
Ilya Nikolaevskiy6aca0b72019-02-13 11:55:57 +010068 RTC_CHECK(video_frame_buffer_ != nullptr);
Artem Titov1ebfb6a2019-01-03 23:49:37 +010069 return VideoFrame(id_, video_frame_buffer_, timestamp_us_, timestamp_rtp_,
Chen Xingf00bf422019-06-20 10:05:55 +020070 ntp_time_ms_, rotation_, color_space_, update_rect_,
Markus Handelle6eded32019-11-15 16:18:21 +010071 packet_infos_, encoded_frame_buffer_);
Emircan Uysaler800787f2018-07-16 10:01:49 -070072}
73
74VideoFrame::Builder& VideoFrame::Builder::set_video_frame_buffer(
75 const rtc::scoped_refptr<VideoFrameBuffer>& buffer) {
76 video_frame_buffer_ = buffer;
77 return *this;
78}
79
80VideoFrame::Builder& VideoFrame::Builder::set_timestamp_ms(
81 int64_t timestamp_ms) {
82 timestamp_us_ = timestamp_ms * rtc::kNumMicrosecsPerMillisec;
83 return *this;
84}
85
86VideoFrame::Builder& VideoFrame::Builder::set_timestamp_us(
87 int64_t timestamp_us) {
88 timestamp_us_ = timestamp_us;
89 return *this;
90}
91
92VideoFrame::Builder& VideoFrame::Builder::set_timestamp_rtp(
93 uint32_t timestamp_rtp) {
94 timestamp_rtp_ = timestamp_rtp;
95 return *this;
96}
97
98VideoFrame::Builder& VideoFrame::Builder::set_ntp_time_ms(int64_t ntp_time_ms) {
99 ntp_time_ms_ = ntp_time_ms;
100 return *this;
101}
102
103VideoFrame::Builder& VideoFrame::Builder::set_rotation(VideoRotation rotation) {
104 rotation_ = rotation;
105 return *this;
106}
107
108VideoFrame::Builder& VideoFrame::Builder::set_color_space(
Danil Chapovalovb7698942019-02-05 11:32:19 +0100109 const absl::optional<ColorSpace>& color_space) {
Emircan Uysaler800787f2018-07-16 10:01:49 -0700110 color_space_ = color_space;
111 return *this;
112}
113
Johannes Kron4749e4e2018-11-21 10:18:18 +0100114VideoFrame::Builder& VideoFrame::Builder::set_color_space(
115 const ColorSpace* color_space) {
116 color_space_ =
117 color_space ? absl::make_optional(*color_space) : absl::nullopt;
Johannes Kronfbf16832018-11-05 16:13:02 +0100118 return *this;
119}
120
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100121VideoFrame::Builder& VideoFrame::Builder::set_id(uint16_t id) {
122 id_ = id;
123 return *this;
124}
125
Ilya Nikolaevskiy6aca0b72019-02-13 11:55:57 +0100126VideoFrame::Builder& VideoFrame::Builder::set_update_rect(
127 const VideoFrame::UpdateRect& update_rect) {
128 update_rect_ = update_rect;
129 return *this;
130}
131
Chen Xingf00bf422019-06-20 10:05:55 +0200132VideoFrame::Builder& VideoFrame::Builder::set_packet_infos(
133 RtpPacketInfos packet_infos) {
134 packet_infos_ = std::move(packet_infos);
135 return *this;
136}
137
Markus Handelle6eded32019-11-15 16:18:21 +0100138VideoFrame::Builder& VideoFrame::Builder::set_encoded_video_frame_buffer(
139 rtc::scoped_refptr<VideoFrame::EncodedVideoFrameBuffer>
140 encoded_frame_buffer) {
141 encoded_frame_buffer_ = std::move(encoded_frame_buffer);
142 return *this;
143}
144
nisseaf916892017-01-10 07:44:26 -0800145VideoFrame::VideoFrame(const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
146 webrtc::VideoRotation rotation,
147 int64_t timestamp_us)
148 : video_frame_buffer_(buffer),
149 timestamp_rtp_(0),
150 ntp_time_ms_(0),
151 timestamp_us_(timestamp_us),
Ilya Nikolaevskiy9560d7d2019-10-30 11:19:47 +0100152 rotation_(rotation) {}
nisseaf916892017-01-10 07:44:26 -0800153
154VideoFrame::VideoFrame(const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
Niels Möller2ac64462018-06-11 11:14:32 +0200155 uint32_t timestamp_rtp,
nisseaf916892017-01-10 07:44:26 -0800156 int64_t render_time_ms,
157 VideoRotation rotation)
158 : video_frame_buffer_(buffer),
Niels Möller2ac64462018-06-11 11:14:32 +0200159 timestamp_rtp_(timestamp_rtp),
nisseaf916892017-01-10 07:44:26 -0800160 ntp_time_ms_(0),
161 timestamp_us_(render_time_ms * rtc::kNumMicrosecsPerMillisec),
Ilya Nikolaevskiy9560d7d2019-10-30 11:19:47 +0100162 rotation_(rotation) {
nisseaf916892017-01-10 07:44:26 -0800163 RTC_DCHECK(buffer);
164}
165
Markus Handelle6eded32019-11-15 16:18:21 +0100166VideoFrame::VideoFrame(
167 uint16_t id,
168 const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
169 int64_t timestamp_us,
170 uint32_t timestamp_rtp,
171 int64_t ntp_time_ms,
172 VideoRotation rotation,
173 const absl::optional<ColorSpace>& color_space,
174 const absl::optional<UpdateRect>& update_rect,
175 RtpPacketInfos packet_infos,
176 const rtc::scoped_refptr<EncodedVideoFrameBuffer>& encoded_frame_buffer)
Artem Titov1ebfb6a2019-01-03 23:49:37 +0100177 : id_(id),
178 video_frame_buffer_(buffer),
Markus Handelle6eded32019-11-15 16:18:21 +0100179 encoded_frame_buffer_(encoded_frame_buffer),
Emircan Uysaler800787f2018-07-16 10:01:49 -0700180 timestamp_rtp_(timestamp_rtp),
181 ntp_time_ms_(ntp_time_ms),
182 timestamp_us_(timestamp_us),
183 rotation_(rotation),
Ilya Nikolaevskiy6aca0b72019-02-13 11:55:57 +0100184 color_space_(color_space),
Ilya Nikolaevskiy9560d7d2019-10-30 11:19:47 +0100185 update_rect_(update_rect),
Chen Xingf00bf422019-06-20 10:05:55 +0200186 packet_infos_(std::move(packet_infos)) {
Ilya Nikolaevskiy9560d7d2019-10-30 11:19:47 +0100187 if (update_rect_) {
188 RTC_DCHECK_GE(update_rect_->offset_x, 0);
189 RTC_DCHECK_GE(update_rect_->offset_y, 0);
190 RTC_DCHECK_LE(update_rect_->offset_x + update_rect_->width, width());
191 RTC_DCHECK_LE(update_rect_->offset_y + update_rect_->height, height());
192 }
Ilya Nikolaevskiy6aca0b72019-02-13 11:55:57 +0100193}
Emircan Uysaler800787f2018-07-16 10:01:49 -0700194
nisseaf916892017-01-10 07:44:26 -0800195VideoFrame::~VideoFrame() = default;
196
197VideoFrame::VideoFrame(const VideoFrame&) = default;
198VideoFrame::VideoFrame(VideoFrame&&) = default;
199VideoFrame& VideoFrame::operator=(const VideoFrame&) = default;
200VideoFrame& VideoFrame::operator=(VideoFrame&&) = default;
201
202int VideoFrame::width() const {
203 return video_frame_buffer_ ? video_frame_buffer_->width() : 0;
204}
205
206int VideoFrame::height() const {
207 return video_frame_buffer_ ? video_frame_buffer_->height() : 0;
208}
209
kthelgason2bc68642017-02-07 07:02:22 -0800210uint32_t VideoFrame::size() const {
211 return width() * height();
212}
213
nisseaf916892017-01-10 07:44:26 -0800214rtc::scoped_refptr<VideoFrameBuffer> VideoFrame::video_frame_buffer() const {
215 return video_frame_buffer_;
216}
217
Ilya Nikolaevskiy4fc08552019-06-05 15:59:12 +0200218void VideoFrame::set_video_frame_buffer(
219 const rtc::scoped_refptr<VideoFrameBuffer>& buffer) {
220 RTC_CHECK(buffer);
221 video_frame_buffer_ = buffer;
222}
223
nisseaf916892017-01-10 07:44:26 -0800224int64_t VideoFrame::render_time_ms() const {
225 return timestamp_us() / rtc::kNumMicrosecsPerMillisec;
226}
227
Markus Handelle6eded32019-11-15 16:18:21 +0100228void VideoFrame::set_encoded_video_frame_buffer(
229 rtc::scoped_refptr<EncodedVideoFrameBuffer> encoded_frame_buffer) {
230 encoded_frame_buffer_ = std::move(encoded_frame_buffer);
231}
232
233rtc::scoped_refptr<VideoFrame::EncodedVideoFrameBuffer>
234VideoFrame::encoded_video_frame_buffer() const {
235 return encoded_frame_buffer_;
236}
237
nisseaf916892017-01-10 07:44:26 -0800238} // namespace webrtc