blob: fff90defbdfa60fb81b7eaac3d72c1b7bbb12689 [file] [log] [blame]
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +00001/*
2 * Copyright (c) 2015 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
kjellander6f8ce062015-11-16 13:52:24 -080011#include "webrtc/common_video/include/video_frame_buffer.h"
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +000012
Per9b3f56e2015-04-09 13:44:16 +020013#include "webrtc/base/bind.h"
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +000014#include "webrtc/base/checks.h"
15
16// Aligning pointer to 64 bytes for improved performance, e.g. use SIMD.
17static const int kBufferAlignment = 64;
18
19namespace webrtc {
Magnus Jedvertc464f502015-08-25 23:22:08 +020020namespace {
21
22// Used in rtc::Bind to keep a buffer alive until destructor is called.
23static void NoLongerUsedCallback(rtc::scoped_refptr<VideoFrameBuffer> dummy) {}
24
25} // anonymous namespace
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +000026
Magnus Jedvert3318f982015-08-26 16:06:21 +020027uint8_t* VideoFrameBuffer::MutableData(PlaneType type) {
28 RTC_NOTREACHED();
29 return nullptr;
30}
31
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +000032VideoFrameBuffer::~VideoFrameBuffer() {}
33
34I420Buffer::I420Buffer(int width, int height)
35 : I420Buffer(width, height, width, (width + 1) / 2, (width + 1) / 2) {
36}
37
38I420Buffer::I420Buffer(int width,
39 int height,
40 int stride_y,
41 int stride_u,
42 int stride_v)
43 : width_(width),
44 height_(height),
45 stride_y_(stride_y),
46 stride_u_(stride_u),
47 stride_v_(stride_v),
48 data_(static_cast<uint8_t*>(AlignedMalloc(
49 stride_y * height + (stride_u + stride_v) * ((height + 1) / 2),
50 kBufferAlignment))) {
henrikg91d6ede2015-09-17 00:24:34 -070051 RTC_DCHECK_GT(width, 0);
52 RTC_DCHECK_GT(height, 0);
53 RTC_DCHECK_GE(stride_y, width);
54 RTC_DCHECK_GE(stride_u, (width + 1) / 2);
55 RTC_DCHECK_GE(stride_v, (width + 1) / 2);
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +000056}
57
58I420Buffer::~I420Buffer() {
59}
60
61int I420Buffer::width() const {
62 return width_;
63}
64
65int I420Buffer::height() const {
66 return height_;
67}
68
69const uint8_t* I420Buffer::data(PlaneType type) const {
70 switch (type) {
71 case kYPlane:
72 return data_.get();
73 case kUPlane:
74 return data_.get() + stride_y_ * height_;
75 case kVPlane:
76 return data_.get() + stride_y_ * height_ +
77 stride_u_ * ((height_ + 1) / 2);
78 default:
79 RTC_NOTREACHED();
80 return nullptr;
81 }
82}
83
Magnus Jedvert3318f982015-08-26 16:06:21 +020084uint8_t* I420Buffer::MutableData(PlaneType type) {
henrikg91d6ede2015-09-17 00:24:34 -070085 RTC_DCHECK(HasOneRef());
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +000086 return const_cast<uint8_t*>(
87 static_cast<const VideoFrameBuffer*>(this)->data(type));
88}
89
90int I420Buffer::stride(PlaneType type) const {
91 switch (type) {
92 case kYPlane:
93 return stride_y_;
94 case kUPlane:
95 return stride_u_;
96 case kVPlane:
97 return stride_v_;
98 default:
99 RTC_NOTREACHED();
100 return 0;
101 }
102}
103
Per9b3f56e2015-04-09 13:44:16 +0200104void* I420Buffer::native_handle() const {
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +0000105 return nullptr;
106}
107
Peter Boströmeb66e802015-06-05 11:08:03 +0200108rtc::scoped_refptr<VideoFrameBuffer> I420Buffer::NativeToI420Buffer() {
109 RTC_NOTREACHED();
110 return nullptr;
111}
112
113NativeHandleBuffer::NativeHandleBuffer(void* native_handle,
114 int width,
115 int height)
116 : native_handle_(native_handle), width_(width), height_(height) {
henrikg91d6ede2015-09-17 00:24:34 -0700117 RTC_DCHECK(native_handle != nullptr);
118 RTC_DCHECK_GT(width, 0);
119 RTC_DCHECK_GT(height, 0);
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +0000120}
121
Peter Boströmeb66e802015-06-05 11:08:03 +0200122int NativeHandleBuffer::width() const {
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +0000123 return width_;
124}
125
Peter Boströmeb66e802015-06-05 11:08:03 +0200126int NativeHandleBuffer::height() const {
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +0000127 return height_;
128}
129
Peter Boströmeb66e802015-06-05 11:08:03 +0200130const uint8_t* NativeHandleBuffer::data(PlaneType type) const {
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +0000131 RTC_NOTREACHED(); // Should not be called.
132 return nullptr;
133}
134
Peter Boströmeb66e802015-06-05 11:08:03 +0200135int NativeHandleBuffer::stride(PlaneType type) const {
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +0000136 RTC_NOTREACHED(); // Should not be called.
137 return 0;
138}
139
Peter Boströmeb66e802015-06-05 11:08:03 +0200140void* NativeHandleBuffer::native_handle() const {
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +0000141 return native_handle_;
142}
143
Magnus Jedvertc464f502015-08-25 23:22:08 +0200144WrappedI420Buffer::WrappedI420Buffer(int width,
Per33544192015-04-02 12:30:51 +0200145 int height,
146 const uint8_t* y_plane,
147 int y_stride,
148 const uint8_t* u_plane,
149 int u_stride,
150 const uint8_t* v_plane,
151 int v_stride,
152 const rtc::Callback0<void>& no_longer_used)
Magnus Jedvertc464f502015-08-25 23:22:08 +0200153 : width_(width),
154 height_(height),
155 y_plane_(y_plane),
156 u_plane_(u_plane),
157 v_plane_(v_plane),
158 y_stride_(y_stride),
159 u_stride_(u_stride),
160 v_stride_(v_stride),
161 no_longer_used_cb_(no_longer_used) {
Per33544192015-04-02 12:30:51 +0200162}
163
164WrappedI420Buffer::~WrappedI420Buffer() {
165 no_longer_used_cb_();
166}
167
Per33544192015-04-02 12:30:51 +0200168int WrappedI420Buffer::width() const {
169 return width_;
170}
171
172int WrappedI420Buffer::height() const {
173 return height_;
174}
175
176const uint8_t* WrappedI420Buffer::data(PlaneType type) const {
177 switch (type) {
178 case kYPlane:
179 return y_plane_;
180 case kUPlane:
181 return u_plane_;
182 case kVPlane:
183 return v_plane_;
184 default:
185 RTC_NOTREACHED();
186 return nullptr;
187 }
188}
189
Per33544192015-04-02 12:30:51 +0200190int WrappedI420Buffer::stride(PlaneType type) const {
191 switch (type) {
192 case kYPlane:
193 return y_stride_;
194 case kUPlane:
195 return u_stride_;
196 case kVPlane:
197 return v_stride_;
198 default:
199 RTC_NOTREACHED();
200 return 0;
201 }
202}
203
Per9b3f56e2015-04-09 13:44:16 +0200204void* WrappedI420Buffer::native_handle() const {
Per33544192015-04-02 12:30:51 +0200205 return nullptr;
206}
207
Peter Boströmeb66e802015-06-05 11:08:03 +0200208rtc::scoped_refptr<VideoFrameBuffer> WrappedI420Buffer::NativeToI420Buffer() {
209 RTC_NOTREACHED();
210 return nullptr;
211}
212
Magnus Jedvertc464f502015-08-25 23:22:08 +0200213rtc::scoped_refptr<VideoFrameBuffer> ShallowCenterCrop(
214 const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
215 int cropped_width,
216 int cropped_height) {
henrikg91d6ede2015-09-17 00:24:34 -0700217 RTC_CHECK(buffer->native_handle() == nullptr);
218 RTC_CHECK_LE(cropped_width, buffer->width());
219 RTC_CHECK_LE(cropped_height, buffer->height());
Magnus Jedvertc464f502015-08-25 23:22:08 +0200220 if (buffer->width() == cropped_width && buffer->height() == cropped_height)
221 return buffer;
222
223 // Center crop to |cropped_width| x |cropped_height|.
224 // Make sure offset is even so that u/v plane becomes aligned.
225 const int uv_offset_x = (buffer->width() - cropped_width) / 4;
226 const int uv_offset_y = (buffer->height() - cropped_height) / 4;
227 const int offset_x = uv_offset_x * 2;
228 const int offset_y = uv_offset_y * 2;
229
Magnus Jedvert3318f982015-08-26 16:06:21 +0200230 const uint8_t* y_plane = buffer->data(kYPlane) +
Magnus Jedvertc464f502015-08-25 23:22:08 +0200231 buffer->stride(kYPlane) * offset_y + offset_x;
Magnus Jedvert3318f982015-08-26 16:06:21 +0200232 const uint8_t* u_plane = buffer->data(kUPlane) +
Magnus Jedvertc464f502015-08-25 23:22:08 +0200233 buffer->stride(kUPlane) * uv_offset_y + uv_offset_x;
Magnus Jedvert3318f982015-08-26 16:06:21 +0200234 const uint8_t* v_plane = buffer->data(kVPlane) +
Magnus Jedvertc464f502015-08-25 23:22:08 +0200235 buffer->stride(kVPlane) * uv_offset_y + uv_offset_x;
236 return new rtc::RefCountedObject<WrappedI420Buffer>(
237 cropped_width, cropped_height,
238 y_plane, buffer->stride(kYPlane),
239 u_plane, buffer->stride(kUPlane),
240 v_plane, buffer->stride(kVPlane),
241 rtc::Bind(&NoLongerUsedCallback, buffer));
242}
243
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +0000244} // namespace webrtc