blob: 492bc495876a6a21b080252686991c89a2f5840b [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
13#include "webrtc/base/checks.h"
perkj14f41442015-11-30 22:15:45 -080014#include "webrtc/base/keep_ref_until_done.h"
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +000015
16// Aligning pointer to 64 bytes for improved performance, e.g. use SIMD.
17static const int kBufferAlignment = 64;
18
19namespace webrtc {
20
Magnus Jedvert3318f982015-08-26 16:06:21 +020021uint8_t* VideoFrameBuffer::MutableData(PlaneType type) {
22 RTC_NOTREACHED();
23 return nullptr;
24}
25
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +000026VideoFrameBuffer::~VideoFrameBuffer() {}
27
28I420Buffer::I420Buffer(int width, int height)
29 : I420Buffer(width, height, width, (width + 1) / 2, (width + 1) / 2) {
30}
31
32I420Buffer::I420Buffer(int width,
33 int height,
34 int stride_y,
35 int stride_u,
36 int stride_v)
37 : width_(width),
38 height_(height),
39 stride_y_(stride_y),
40 stride_u_(stride_u),
41 stride_v_(stride_v),
42 data_(static_cast<uint8_t*>(AlignedMalloc(
43 stride_y * height + (stride_u + stride_v) * ((height + 1) / 2),
44 kBufferAlignment))) {
henrikg91d6ede2015-09-17 00:24:34 -070045 RTC_DCHECK_GT(width, 0);
46 RTC_DCHECK_GT(height, 0);
47 RTC_DCHECK_GE(stride_y, width);
48 RTC_DCHECK_GE(stride_u, (width + 1) / 2);
49 RTC_DCHECK_GE(stride_v, (width + 1) / 2);
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +000050}
51
52I420Buffer::~I420Buffer() {
53}
54
55int I420Buffer::width() const {
56 return width_;
57}
58
59int I420Buffer::height() const {
60 return height_;
61}
62
63const uint8_t* I420Buffer::data(PlaneType type) const {
64 switch (type) {
65 case kYPlane:
66 return data_.get();
67 case kUPlane:
68 return data_.get() + stride_y_ * height_;
69 case kVPlane:
70 return data_.get() + stride_y_ * height_ +
71 stride_u_ * ((height_ + 1) / 2);
72 default:
73 RTC_NOTREACHED();
74 return nullptr;
75 }
76}
77
Magnus Jedvert3318f982015-08-26 16:06:21 +020078uint8_t* I420Buffer::MutableData(PlaneType type) {
henrikg91d6ede2015-09-17 00:24:34 -070079 RTC_DCHECK(HasOneRef());
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +000080 return const_cast<uint8_t*>(
81 static_cast<const VideoFrameBuffer*>(this)->data(type));
82}
83
84int I420Buffer::stride(PlaneType type) const {
85 switch (type) {
86 case kYPlane:
87 return stride_y_;
88 case kUPlane:
89 return stride_u_;
90 case kVPlane:
91 return stride_v_;
92 default:
93 RTC_NOTREACHED();
94 return 0;
95 }
96}
97
Per9b3f56e2015-04-09 13:44:16 +020098void* I420Buffer::native_handle() const {
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +000099 return nullptr;
100}
101
Peter Boströmeb66e802015-06-05 11:08:03 +0200102rtc::scoped_refptr<VideoFrameBuffer> I420Buffer::NativeToI420Buffer() {
103 RTC_NOTREACHED();
104 return nullptr;
105}
106
107NativeHandleBuffer::NativeHandleBuffer(void* native_handle,
108 int width,
109 int height)
110 : native_handle_(native_handle), width_(width), height_(height) {
henrikg91d6ede2015-09-17 00:24:34 -0700111 RTC_DCHECK(native_handle != nullptr);
112 RTC_DCHECK_GT(width, 0);
113 RTC_DCHECK_GT(height, 0);
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +0000114}
115
Peter Boströmeb66e802015-06-05 11:08:03 +0200116int NativeHandleBuffer::width() const {
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +0000117 return width_;
118}
119
Peter Boströmeb66e802015-06-05 11:08:03 +0200120int NativeHandleBuffer::height() const {
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +0000121 return height_;
122}
123
Peter Boströmeb66e802015-06-05 11:08:03 +0200124const uint8_t* NativeHandleBuffer::data(PlaneType type) const {
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +0000125 RTC_NOTREACHED(); // Should not be called.
126 return nullptr;
127}
128
Peter Boströmeb66e802015-06-05 11:08:03 +0200129int NativeHandleBuffer::stride(PlaneType type) const {
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +0000130 RTC_NOTREACHED(); // Should not be called.
131 return 0;
132}
133
Peter Boströmeb66e802015-06-05 11:08:03 +0200134void* NativeHandleBuffer::native_handle() const {
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +0000135 return native_handle_;
136}
137
Magnus Jedvertc464f502015-08-25 23:22:08 +0200138WrappedI420Buffer::WrappedI420Buffer(int width,
Per33544192015-04-02 12:30:51 +0200139 int height,
140 const uint8_t* y_plane,
141 int y_stride,
142 const uint8_t* u_plane,
143 int u_stride,
144 const uint8_t* v_plane,
145 int v_stride,
146 const rtc::Callback0<void>& no_longer_used)
Magnus Jedvertc464f502015-08-25 23:22:08 +0200147 : width_(width),
148 height_(height),
149 y_plane_(y_plane),
150 u_plane_(u_plane),
151 v_plane_(v_plane),
152 y_stride_(y_stride),
153 u_stride_(u_stride),
154 v_stride_(v_stride),
155 no_longer_used_cb_(no_longer_used) {
Per33544192015-04-02 12:30:51 +0200156}
157
158WrappedI420Buffer::~WrappedI420Buffer() {
159 no_longer_used_cb_();
160}
161
Per33544192015-04-02 12:30:51 +0200162int WrappedI420Buffer::width() const {
163 return width_;
164}
165
166int WrappedI420Buffer::height() const {
167 return height_;
168}
169
170const uint8_t* WrappedI420Buffer::data(PlaneType type) const {
171 switch (type) {
172 case kYPlane:
173 return y_plane_;
174 case kUPlane:
175 return u_plane_;
176 case kVPlane:
177 return v_plane_;
178 default:
179 RTC_NOTREACHED();
180 return nullptr;
181 }
182}
183
Per33544192015-04-02 12:30:51 +0200184int WrappedI420Buffer::stride(PlaneType type) const {
185 switch (type) {
186 case kYPlane:
187 return y_stride_;
188 case kUPlane:
189 return u_stride_;
190 case kVPlane:
191 return v_stride_;
192 default:
193 RTC_NOTREACHED();
194 return 0;
195 }
196}
197
Per9b3f56e2015-04-09 13:44:16 +0200198void* WrappedI420Buffer::native_handle() const {
Per33544192015-04-02 12:30:51 +0200199 return nullptr;
200}
201
Peter Boströmeb66e802015-06-05 11:08:03 +0200202rtc::scoped_refptr<VideoFrameBuffer> WrappedI420Buffer::NativeToI420Buffer() {
203 RTC_NOTREACHED();
204 return nullptr;
205}
206
Magnus Jedvertc464f502015-08-25 23:22:08 +0200207rtc::scoped_refptr<VideoFrameBuffer> ShallowCenterCrop(
208 const rtc::scoped_refptr<VideoFrameBuffer>& buffer,
209 int cropped_width,
210 int cropped_height) {
henrikg91d6ede2015-09-17 00:24:34 -0700211 RTC_CHECK(buffer->native_handle() == nullptr);
212 RTC_CHECK_LE(cropped_width, buffer->width());
213 RTC_CHECK_LE(cropped_height, buffer->height());
Magnus Jedvertc464f502015-08-25 23:22:08 +0200214 if (buffer->width() == cropped_width && buffer->height() == cropped_height)
215 return buffer;
216
217 // Center crop to |cropped_width| x |cropped_height|.
218 // Make sure offset is even so that u/v plane becomes aligned.
219 const int uv_offset_x = (buffer->width() - cropped_width) / 4;
220 const int uv_offset_y = (buffer->height() - cropped_height) / 4;
221 const int offset_x = uv_offset_x * 2;
222 const int offset_y = uv_offset_y * 2;
223
Magnus Jedvert3318f982015-08-26 16:06:21 +0200224 const uint8_t* y_plane = buffer->data(kYPlane) +
Magnus Jedvertc464f502015-08-25 23:22:08 +0200225 buffer->stride(kYPlane) * offset_y + offset_x;
Magnus Jedvert3318f982015-08-26 16:06:21 +0200226 const uint8_t* u_plane = buffer->data(kUPlane) +
Magnus Jedvertc464f502015-08-25 23:22:08 +0200227 buffer->stride(kUPlane) * uv_offset_y + uv_offset_x;
Magnus Jedvert3318f982015-08-26 16:06:21 +0200228 const uint8_t* v_plane = buffer->data(kVPlane) +
Magnus Jedvertc464f502015-08-25 23:22:08 +0200229 buffer->stride(kVPlane) * uv_offset_y + uv_offset_x;
230 return new rtc::RefCountedObject<WrappedI420Buffer>(
231 cropped_width, cropped_height,
232 y_plane, buffer->stride(kYPlane),
233 u_plane, buffer->stride(kUPlane),
234 v_plane, buffer->stride(kVPlane),
perkj14f41442015-11-30 22:15:45 -0800235 rtc::KeepRefUntilDone(buffer));
Magnus Jedvertc464f502015-08-25 23:22:08 +0200236}
237
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +0000238} // namespace webrtc