blob: 9c127602df0b08a0ea98ff66dbbd23a30ba29101 [file] [log] [blame]
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -07001/*
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 "webrtc/video_frame.h"
12
13#include <string.h>
14
15#include <algorithm> // swap
16
17#include "webrtc/base/bind.h"
18#include "webrtc/base/checks.h"
19
20namespace webrtc {
21
22VideoFrame::VideoFrame() {
23 // Intentionally using Reset instead of initializer list so that any missed
24 // fields in Reset will be caught by memory checkers.
25 Reset();
26}
27
28VideoFrame::VideoFrame(const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
29 uint32_t timestamp,
30 int64_t render_time_ms,
31 VideoRotation rotation)
32 : video_frame_buffer_(buffer),
33 timestamp_(timestamp),
34 ntp_time_ms_(0),
35 render_time_ms_(render_time_ms),
36 rotation_(rotation) {
37}
38
Peter Boström308d1632015-06-02 15:04:23 +020039VideoFrame::VideoFrame(void* native_handle,
40 int width,
41 int height,
42 uint32_t timestamp,
43 int64_t render_time_ms,
44 VideoRotation rotation,
45 const rtc::Callback0<void>& no_longer_used)
46 : VideoFrame(new rtc::RefCountedObject<TextureBuffer>(native_handle,
47 width,
48 height,
49 no_longer_used),
50 timestamp,
51 render_time_ms,
52 rotation) {
53}
54
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -070055int VideoFrame::CreateEmptyFrame(int width,
56 int height,
57 int stride_y,
58 int stride_u,
59 int stride_v) {
60 const int half_width = (width + 1) / 2;
61 DCHECK_GT(width, 0);
62 DCHECK_GT(height, 0);
63 DCHECK_GE(stride_y, width);
64 DCHECK_GE(stride_u, half_width);
65 DCHECK_GE(stride_v, half_width);
66
67 // Creating empty frame - reset all values.
68 timestamp_ = 0;
69 ntp_time_ms_ = 0;
70 render_time_ms_ = 0;
71 rotation_ = kVideoRotation_0;
72
73 // Check if it's safe to reuse allocation.
74 if (video_frame_buffer_ && video_frame_buffer_->HasOneRef() &&
75 !video_frame_buffer_->native_handle() &&
76 width == video_frame_buffer_->width() &&
77 height == video_frame_buffer_->height() && stride_y == stride(kYPlane) &&
78 stride_u == stride(kUPlane) && stride_v == stride(kVPlane)) {
79 return 0;
80 }
81
82 // Need to allocate new buffer.
83 video_frame_buffer_ = new rtc::RefCountedObject<I420Buffer>(
84 width, height, stride_y, stride_u, stride_v);
85 return 0;
86}
87
88int VideoFrame::CreateFrame(const uint8_t* buffer_y,
89 const uint8_t* buffer_u,
90 const uint8_t* buffer_v,
91 int width,
92 int height,
93 int stride_y,
94 int stride_u,
95 int stride_v) {
96 return CreateFrame(buffer_y, buffer_u, buffer_v, width, height, stride_y,
97 stride_u, stride_v, kVideoRotation_0);
98}
99
100int VideoFrame::CreateFrame(const uint8_t* buffer_y,
101 const uint8_t* buffer_u,
102 const uint8_t* buffer_v,
103 int width,
104 int height,
105 int stride_y,
106 int stride_u,
107 int stride_v,
108 VideoRotation rotation) {
109 const int half_height = (height + 1) / 2;
110 const int expected_size_y = height * stride_y;
111 const int expected_size_u = half_height * stride_u;
112 const int expected_size_v = half_height * stride_v;
113 CreateEmptyFrame(width, height, stride_y, stride_u, stride_v);
114 memcpy(buffer(kYPlane), buffer_y, expected_size_y);
115 memcpy(buffer(kUPlane), buffer_u, expected_size_u);
116 memcpy(buffer(kVPlane), buffer_v, expected_size_v);
117 rotation_ = rotation;
118 return 0;
119}
120
121int VideoFrame::CreateFrame(const uint8_t* buffer,
122 int width,
123 int height,
124 VideoRotation rotation) {
125 const int stride_y = width;
126 const int stride_uv = (width + 1) / 2;
127
128 const uint8_t* buffer_y = buffer;
129 const uint8_t* buffer_u = buffer_y + stride_y * height;
130 const uint8_t* buffer_v = buffer_u + stride_uv * ((height + 1) / 2);
131 return CreateFrame(buffer_y, buffer_u, buffer_v, width, height, stride_y,
132 stride_uv, stride_uv, rotation);
133}
134
135int VideoFrame::CopyFrame(const VideoFrame& videoFrame) {
136 if (videoFrame.IsZeroSize()) {
137 video_frame_buffer_ = nullptr;
138 } else if (videoFrame.native_handle()) {
139 video_frame_buffer_ = videoFrame.video_frame_buffer();
140 } else {
141 CreateFrame(videoFrame.buffer(kYPlane), videoFrame.buffer(kUPlane),
142 videoFrame.buffer(kVPlane), videoFrame.width(),
143 videoFrame.height(), videoFrame.stride(kYPlane),
144 videoFrame.stride(kUPlane), videoFrame.stride(kVPlane));
145 }
146
147 timestamp_ = videoFrame.timestamp_;
148 ntp_time_ms_ = videoFrame.ntp_time_ms_;
149 render_time_ms_ = videoFrame.render_time_ms_;
150 rotation_ = videoFrame.rotation_;
151 return 0;
152}
153
154void VideoFrame::ShallowCopy(const VideoFrame& videoFrame) {
155 video_frame_buffer_ = videoFrame.video_frame_buffer();
156 timestamp_ = videoFrame.timestamp_;
157 ntp_time_ms_ = videoFrame.ntp_time_ms_;
158 render_time_ms_ = videoFrame.render_time_ms_;
159 rotation_ = videoFrame.rotation_;
160}
161
162void VideoFrame::Reset() {
163 video_frame_buffer_ = nullptr;
164 timestamp_ = 0;
165 ntp_time_ms_ = 0;
166 render_time_ms_ = 0;
167 rotation_ = kVideoRotation_0;
168}
169
170uint8_t* VideoFrame::buffer(PlaneType type) {
171 return video_frame_buffer_ ? video_frame_buffer_->data(type) : nullptr;
172}
173
174const uint8_t* VideoFrame::buffer(PlaneType type) const {
175 // Const cast to call the correct const-version of data.
176 const VideoFrameBuffer* const_buffer = video_frame_buffer_.get();
177 return const_buffer ? const_buffer->data(type) : nullptr;
178}
179
180int VideoFrame::allocated_size(PlaneType type) const {
181 const int plane_height = (type == kYPlane) ? height() : (height() + 1) / 2;
182 return plane_height * stride(type);
183}
184
185int VideoFrame::stride(PlaneType type) const {
186 return video_frame_buffer_ ? video_frame_buffer_->stride(type) : 0;
187}
188
189int VideoFrame::width() const {
190 return video_frame_buffer_ ? video_frame_buffer_->width() : 0;
191}
192
193int VideoFrame::height() const {
194 return video_frame_buffer_ ? video_frame_buffer_->height() : 0;
195}
196
197bool VideoFrame::IsZeroSize() const {
198 return !video_frame_buffer_;
199}
200
201void* VideoFrame::native_handle() const {
202 return video_frame_buffer_ ? video_frame_buffer_->native_handle() : nullptr;
203}
204
205rtc::scoped_refptr<VideoFrameBuffer> VideoFrame::video_frame_buffer() const {
206 return video_frame_buffer_;
207}
208
209void VideoFrame::set_video_frame_buffer(
210 const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& buffer) {
211 video_frame_buffer_ = buffer;
212}
213
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700214} // namespace webrtc