blob: 2cd0b290f151d00281cf0b13baa0eb4eaadd5303 [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 */
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020010#include "common_video/include/video_frame_buffer.h"
perkj0489e492016-10-20 00:24:01 -070011
12#include <string.h>
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +000013
Niels Möller718a7632016-06-13 13:06:01 +020014#include <algorithm>
15
Patrik Höglundb5b5bce2017-11-13 10:19:58 +010016#include "api/video/i420_buffer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "rtc_base/checks.h"
18#include "rtc_base/keep_ref_until_done.h"
Mirko Bonadei65432062017-12-11 09:32:13 +010019#include "third_party/libyuv/include/libyuv/convert.h"
20#include "third_party/libyuv/include/libyuv/planar_functions.h"
21#include "third_party/libyuv/include/libyuv/scale.h"
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +000022
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +000023namespace webrtc {
24
Patrik Höglundb5b5bce2017-11-13 10:19:58 +010025namespace {
Per33544192015-04-02 12:30:51 +020026
yuweih23cc4682017-06-22 20:28:06 -070027// Template to implement a wrapped buffer for a I4??BufferInterface.
28template <typename Base>
29class WrappedYuvBuffer : public Base {
30 public:
31 WrappedYuvBuffer(int width,
32 int height,
33 const uint8_t* y_plane,
34 int y_stride,
35 const uint8_t* u_plane,
36 int u_stride,
37 const uint8_t* v_plane,
38 int v_stride,
39 const rtc::Callback0<void>& no_longer_used)
40 : width_(width),
41 height_(height),
42 y_plane_(y_plane),
43 u_plane_(u_plane),
44 v_plane_(v_plane),
45 y_stride_(y_stride),
46 u_stride_(u_stride),
47 v_stride_(v_stride),
48 no_longer_used_cb_(no_longer_used) {}
49
Emircan Uysaler574eaa42017-11-09 12:33:24 -080050 ~WrappedYuvBuffer() override { no_longer_used_cb_(); }
51
yuweih23cc4682017-06-22 20:28:06 -070052 int width() const override { return width_; }
53
54 int height() const override { return height_; }
55
56 const uint8_t* DataY() const override { return y_plane_; }
57
58 const uint8_t* DataU() const override { return u_plane_; }
59
60 const uint8_t* DataV() const override { return v_plane_; }
61
62 int StrideY() const override { return y_stride_; }
63
64 int StrideU() const override { return u_stride_; }
65
66 int StrideV() const override { return v_stride_; }
67
68 private:
69 friend class rtc::RefCountedObject<WrappedYuvBuffer>;
70
yuweih23cc4682017-06-22 20:28:06 -070071 const int width_;
72 const int height_;
73 const uint8_t* const y_plane_;
74 const uint8_t* const u_plane_;
75 const uint8_t* const v_plane_;
76 const int y_stride_;
77 const int u_stride_;
78 const int v_stride_;
79 rtc::Callback0<void> no_longer_used_cb_;
80};
81
Emircan Uysaler574eaa42017-11-09 12:33:24 -080082// Template to implement a wrapped buffer for a I4??BufferInterface.
83template <typename BaseWithA>
84class WrappedYuvaBuffer : public WrappedYuvBuffer<BaseWithA> {
85 public:
86 WrappedYuvaBuffer(int width,
87 int height,
88 const uint8_t* y_plane,
89 int y_stride,
90 const uint8_t* u_plane,
91 int u_stride,
92 const uint8_t* v_plane,
93 int v_stride,
94 const uint8_t* a_plane,
95 int a_stride,
96 const rtc::Callback0<void>& no_longer_used)
97 : WrappedYuvBuffer<BaseWithA>(width,
98 height,
99 y_plane,
100 y_stride,
101 u_plane,
102 u_stride,
103 v_plane,
104 v_stride,
105 no_longer_used),
106 a_plane_(a_plane),
107 a_stride_(a_stride) {}
108
109 const uint8_t* DataA() const override { return a_plane_; }
110 int StrideA() const override { return a_stride_; }
111
112 private:
113 const uint8_t* const a_plane_;
114 const int a_stride_;
115};
116
Patrik Höglundb5b5bce2017-11-13 10:19:58 +0100117class I444BufferBase : public I444BufferInterface {
118 public:
119 rtc::scoped_refptr<I420BufferInterface> ToI420() final;
120};
121
122rtc::scoped_refptr<I420BufferInterface> I444BufferBase::ToI420() {
123 rtc::scoped_refptr<I420Buffer> i420_buffer =
124 I420Buffer::Create(width(), height());
125 libyuv::I444ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(),
126 i420_buffer->MutableDataY(), i420_buffer->StrideY(),
127 i420_buffer->MutableDataU(), i420_buffer->StrideU(),
128 i420_buffer->MutableDataV(), i420_buffer->StrideV(),
129 width(), height());
130 return i420_buffer;
131}
132
Emircan Uysaler901e0ff2018-06-26 12:22:38 -0700133// Template to implement a wrapped buffer for a PlanarYuv16BBuffer.
134template <typename Base>
135class WrappedYuv16BBuffer : public Base {
136 public:
137 WrappedYuv16BBuffer(int width,
138 int height,
139 const uint16_t* y_plane,
140 int y_stride,
141 const uint16_t* u_plane,
142 int u_stride,
143 const uint16_t* v_plane,
144 int v_stride,
145 const rtc::Callback0<void>& no_longer_used)
146 : width_(width),
147 height_(height),
148 y_plane_(y_plane),
149 u_plane_(u_plane),
150 v_plane_(v_plane),
151 y_stride_(y_stride),
152 u_stride_(u_stride),
153 v_stride_(v_stride),
154 no_longer_used_cb_(no_longer_used) {}
155
156 ~WrappedYuv16BBuffer() override { no_longer_used_cb_(); }
157
158 int width() const override { return width_; }
159
160 int height() const override { return height_; }
161
162 const uint16_t* DataY() const override { return y_plane_; }
163
164 const uint16_t* DataU() const override { return u_plane_; }
165
166 const uint16_t* DataV() const override { return v_plane_; }
167
168 int StrideY() const override { return y_stride_; }
169
170 int StrideU() const override { return u_stride_; }
171
172 int StrideV() const override { return v_stride_; }
173
174 private:
175 friend class rtc::RefCountedObject<WrappedYuv16BBuffer>;
176
177 const int width_;
178 const int height_;
179 const uint16_t* const y_plane_;
180 const uint16_t* const u_plane_;
181 const uint16_t* const v_plane_;
182 const int y_stride_;
183 const int u_stride_;
184 const int v_stride_;
185 rtc::Callback0<void> no_longer_used_cb_;
186};
187
188class I010BufferBase : public I010BufferInterface {
189 public:
190 rtc::scoped_refptr<I420BufferInterface> ToI420() final;
191};
192
193rtc::scoped_refptr<I420BufferInterface> I010BufferBase::ToI420() {
194 rtc::scoped_refptr<I420Buffer> i420_buffer =
195 I420Buffer::Create(width(), height());
196 libyuv::I010ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(),
197 i420_buffer->MutableDataY(), i420_buffer->StrideY(),
198 i420_buffer->MutableDataU(), i420_buffer->StrideU(),
199 i420_buffer->MutableDataV(), i420_buffer->StrideV(),
200 width(), height());
201 return i420_buffer;
202}
203
Patrik Höglundb5b5bce2017-11-13 10:19:58 +0100204} // namespace
205
206WrappedI420Buffer::WrappedI420Buffer(int width,
207 int height,
208 const uint8_t* y_plane,
209 int y_stride,
210 const uint8_t* u_plane,
211 int u_stride,
212 const uint8_t* v_plane,
213 int v_stride,
214 const rtc::Callback0<void>& no_longer_used)
215 : width_(width),
216 height_(height),
217 y_plane_(y_plane),
218 u_plane_(u_plane),
219 v_plane_(v_plane),
220 y_stride_(y_stride),
221 u_stride_(u_stride),
222 v_stride_(v_stride),
Yves Gerey665174f2018-06-19 15:03:05 +0200223 no_longer_used_cb_(no_longer_used) {}
Patrik Höglundb5b5bce2017-11-13 10:19:58 +0100224
225WrappedI420Buffer::~WrappedI420Buffer() {
226 no_longer_used_cb_();
227}
228
229int WrappedI420Buffer::width() const {
230 return width_;
231}
232
233int WrappedI420Buffer::height() const {
234 return height_;
235}
236
237const uint8_t* WrappedI420Buffer::DataY() const {
238 return y_plane_;
239}
240const uint8_t* WrappedI420Buffer::DataU() const {
241 return u_plane_;
242}
243const uint8_t* WrappedI420Buffer::DataV() const {
244 return v_plane_;
245}
246
247int WrappedI420Buffer::StrideY() const {
248 return y_stride_;
249}
250int WrappedI420Buffer::StrideU() const {
251 return u_stride_;
252}
253int WrappedI420Buffer::StrideV() const {
254 return v_stride_;
255}
256
yuweih23cc4682017-06-22 20:28:06 -0700257rtc::scoped_refptr<I420BufferInterface> WrapI420Buffer(
258 int width,
259 int height,
260 const uint8_t* y_plane,
261 int y_stride,
262 const uint8_t* u_plane,
263 int u_stride,
264 const uint8_t* v_plane,
265 int v_stride,
266 const rtc::Callback0<void>& no_longer_used) {
267 return rtc::scoped_refptr<I420BufferInterface>(
268 new rtc::RefCountedObject<WrappedYuvBuffer<I420BufferInterface>>(
269 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
270 v_stride, no_longer_used));
271}
272
Emircan Uysaler574eaa42017-11-09 12:33:24 -0800273rtc::scoped_refptr<I420ABufferInterface> WrapI420ABuffer(
274 int width,
275 int height,
276 const uint8_t* y_plane,
277 int y_stride,
278 const uint8_t* u_plane,
279 int u_stride,
280 const uint8_t* v_plane,
281 int v_stride,
282 const uint8_t* a_plane,
283 int a_stride,
284 const rtc::Callback0<void>& no_longer_used) {
285 return rtc::scoped_refptr<I420ABufferInterface>(
286 new rtc::RefCountedObject<WrappedYuvaBuffer<I420ABufferInterface>>(
287 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
288 v_stride, a_plane, a_stride, no_longer_used));
289}
290
yuweih23cc4682017-06-22 20:28:06 -0700291rtc::scoped_refptr<I444BufferInterface> WrapI444Buffer(
292 int width,
293 int height,
294 const uint8_t* y_plane,
295 int y_stride,
296 const uint8_t* u_plane,
297 int u_stride,
298 const uint8_t* v_plane,
299 int v_stride,
300 const rtc::Callback0<void>& no_longer_used) {
301 return rtc::scoped_refptr<I444BufferInterface>(
Patrik Höglundb5b5bce2017-11-13 10:19:58 +0100302 new rtc::RefCountedObject<WrappedYuvBuffer<I444BufferBase>>(
yuweih23cc4682017-06-22 20:28:06 -0700303 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
304 v_stride, no_longer_used));
305}
306
307rtc::scoped_refptr<PlanarYuvBuffer> WrapYuvBuffer(
308 VideoFrameBuffer::Type type,
309 int width,
310 int height,
311 const uint8_t* y_plane,
312 int y_stride,
313 const uint8_t* u_plane,
314 int u_stride,
315 const uint8_t* v_plane,
316 int v_stride,
317 const rtc::Callback0<void>& no_longer_used) {
318 switch (type) {
319 case VideoFrameBuffer::Type::kI420:
320 return WrapI420Buffer(width, height, y_plane, y_stride, u_plane, u_stride,
321 v_plane, v_stride, no_longer_used);
322 case VideoFrameBuffer::Type::kI444:
323 return WrapI444Buffer(width, height, y_plane, y_stride, u_plane, u_stride,
324 v_plane, v_stride, no_longer_used);
325 default:
326 FATAL() << "Unexpected frame buffer type.";
327 return nullptr;
328 }
329}
330
Emircan Uysaler901e0ff2018-06-26 12:22:38 -0700331rtc::scoped_refptr<I010BufferInterface> WrapI010Buffer(
332 int width,
333 int height,
334 const uint16_t* y_plane,
335 int y_stride,
336 const uint16_t* u_plane,
337 int u_stride,
338 const uint16_t* v_plane,
339 int v_stride,
340 const rtc::Callback0<void>& no_longer_used) {
341 return rtc::scoped_refptr<I010BufferInterface>(
342 new rtc::RefCountedObject<WrappedYuv16BBuffer<I010BufferBase>>(
343 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
344 v_stride, no_longer_used));
345}
346
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +0000347} // namespace webrtc