1 /*
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 #include "common_video/include/video_frame_buffer.h"
11
12 #include "api/make_ref_counted.h"
13 #include "api/video/i420_buffer.h"
14 #include "rtc_base/checks.h"
15 #include "third_party/libyuv/include/libyuv/convert.h"
16
17 namespace webrtc {
18
19 namespace {
20
21 // Template to implement a wrapped buffer for a I4??BufferInterface.
22 template <typename Base>
23 class WrappedYuvBuffer : public Base {
24 public:
WrappedYuvBuffer(int width,int height,const uint8_t * y_plane,int y_stride,const uint8_t * u_plane,int u_stride,const uint8_t * v_plane,int v_stride,std::function<void ()> no_longer_used)25 WrappedYuvBuffer(int width,
26 int height,
27 const uint8_t* y_plane,
28 int y_stride,
29 const uint8_t* u_plane,
30 int u_stride,
31 const uint8_t* v_plane,
32 int v_stride,
33 std::function<void()> no_longer_used)
34 : width_(width),
35 height_(height),
36 y_plane_(y_plane),
37 u_plane_(u_plane),
38 v_plane_(v_plane),
39 y_stride_(y_stride),
40 u_stride_(u_stride),
41 v_stride_(v_stride),
42 no_longer_used_cb_(no_longer_used) {}
43
~WrappedYuvBuffer()44 ~WrappedYuvBuffer() override { no_longer_used_cb_(); }
45
width() const46 int width() const override { return width_; }
47
height() const48 int height() const override { return height_; }
49
DataY() const50 const uint8_t* DataY() const override { return y_plane_; }
51
DataU() const52 const uint8_t* DataU() const override { return u_plane_; }
53
DataV() const54 const uint8_t* DataV() const override { return v_plane_; }
55
StrideY() const56 int StrideY() const override { return y_stride_; }
57
StrideU() const58 int StrideU() const override { return u_stride_; }
59
StrideV() const60 int StrideV() const override { return v_stride_; }
61
62 private:
63 friend class rtc::RefCountedObject<WrappedYuvBuffer>;
64
65 const int width_;
66 const int height_;
67 const uint8_t* const y_plane_;
68 const uint8_t* const u_plane_;
69 const uint8_t* const v_plane_;
70 const int y_stride_;
71 const int u_stride_;
72 const int v_stride_;
73 std::function<void()> no_longer_used_cb_;
74 };
75
76 // Template to implement a wrapped buffer for a I4??BufferInterface.
77 template <typename BaseWithA>
78 class WrappedYuvaBuffer : public WrappedYuvBuffer<BaseWithA> {
79 public:
WrappedYuvaBuffer(int width,int height,const uint8_t * y_plane,int y_stride,const uint8_t * u_plane,int u_stride,const uint8_t * v_plane,int v_stride,const uint8_t * a_plane,int a_stride,std::function<void ()> no_longer_used)80 WrappedYuvaBuffer(int width,
81 int height,
82 const uint8_t* y_plane,
83 int y_stride,
84 const uint8_t* u_plane,
85 int u_stride,
86 const uint8_t* v_plane,
87 int v_stride,
88 const uint8_t* a_plane,
89 int a_stride,
90 std::function<void()> no_longer_used)
91 : WrappedYuvBuffer<BaseWithA>(width,
92 height,
93 y_plane,
94 y_stride,
95 u_plane,
96 u_stride,
97 v_plane,
98 v_stride,
99 no_longer_used),
100 a_plane_(a_plane),
101 a_stride_(a_stride) {}
102
DataA() const103 const uint8_t* DataA() const override { return a_plane_; }
StrideA() const104 int StrideA() const override { return a_stride_; }
105
106 private:
107 const uint8_t* const a_plane_;
108 const int a_stride_;
109 };
110
111 class I444BufferBase : public I444BufferInterface {
112 public:
113 rtc::scoped_refptr<I420BufferInterface> ToI420() final;
114 };
115
ToI420()116 rtc::scoped_refptr<I420BufferInterface> I444BufferBase::ToI420() {
117 rtc::scoped_refptr<I420Buffer> i420_buffer =
118 I420Buffer::Create(width(), height());
119 libyuv::I444ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(),
120 i420_buffer->MutableDataY(), i420_buffer->StrideY(),
121 i420_buffer->MutableDataU(), i420_buffer->StrideU(),
122 i420_buffer->MutableDataV(), i420_buffer->StrideV(),
123 width(), height());
124 return i420_buffer;
125 }
126
127 class I422BufferBase : public I422BufferInterface {
128 public:
129 rtc::scoped_refptr<I420BufferInterface> ToI420() final;
130 };
131
ToI420()132 rtc::scoped_refptr<I420BufferInterface> I422BufferBase::ToI420() {
133 rtc::scoped_refptr<I420Buffer> i420_buffer =
134 I420Buffer::Create(width(), height());
135 libyuv::I422ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(),
136 i420_buffer->MutableDataY(), i420_buffer->StrideY(),
137 i420_buffer->MutableDataU(), i420_buffer->StrideU(),
138 i420_buffer->MutableDataV(), i420_buffer->StrideV(),
139 width(), height());
140 return i420_buffer;
141 }
142
143 // Template to implement a wrapped buffer for a PlanarYuv16BBuffer.
144 template <typename Base>
145 class WrappedYuv16BBuffer : public Base {
146 public:
WrappedYuv16BBuffer(int width,int height,const uint16_t * y_plane,int y_stride,const uint16_t * u_plane,int u_stride,const uint16_t * v_plane,int v_stride,std::function<void ()> no_longer_used)147 WrappedYuv16BBuffer(int width,
148 int height,
149 const uint16_t* y_plane,
150 int y_stride,
151 const uint16_t* u_plane,
152 int u_stride,
153 const uint16_t* v_plane,
154 int v_stride,
155 std::function<void()> no_longer_used)
156 : width_(width),
157 height_(height),
158 y_plane_(y_plane),
159 u_plane_(u_plane),
160 v_plane_(v_plane),
161 y_stride_(y_stride),
162 u_stride_(u_stride),
163 v_stride_(v_stride),
164 no_longer_used_cb_(no_longer_used) {}
165
~WrappedYuv16BBuffer()166 ~WrappedYuv16BBuffer() override { no_longer_used_cb_(); }
167
width() const168 int width() const override { return width_; }
169
height() const170 int height() const override { return height_; }
171
DataY() const172 const uint16_t* DataY() const override { return y_plane_; }
173
DataU() const174 const uint16_t* DataU() const override { return u_plane_; }
175
DataV() const176 const uint16_t* DataV() const override { return v_plane_; }
177
StrideY() const178 int StrideY() const override { return y_stride_; }
179
StrideU() const180 int StrideU() const override { return u_stride_; }
181
StrideV() const182 int StrideV() const override { return v_stride_; }
183
184 private:
185 friend class rtc::RefCountedObject<WrappedYuv16BBuffer>;
186
187 const int width_;
188 const int height_;
189 const uint16_t* const y_plane_;
190 const uint16_t* const u_plane_;
191 const uint16_t* const v_plane_;
192 const int y_stride_;
193 const int u_stride_;
194 const int v_stride_;
195 std::function<void()> no_longer_used_cb_;
196 };
197
198 class I010BufferBase : public I010BufferInterface {
199 public:
200 rtc::scoped_refptr<I420BufferInterface> ToI420() final;
201 };
202
ToI420()203 rtc::scoped_refptr<I420BufferInterface> I010BufferBase::ToI420() {
204 rtc::scoped_refptr<I420Buffer> i420_buffer =
205 I420Buffer::Create(width(), height());
206 #if 0
207 libyuv::I010ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(),
208 i420_buffer->MutableDataY(), i420_buffer->StrideY(),
209 i420_buffer->MutableDataU(), i420_buffer->StrideU(),
210 i420_buffer->MutableDataV(), i420_buffer->StrideV(),
211 width(), height());
212 #else
213 abort();
214 #endif
215 return i420_buffer;
216 }
217
218 class I210BufferBase : public I210BufferInterface {
219 public:
220 rtc::scoped_refptr<I420BufferInterface> ToI420() final;
221 };
222
ToI420()223 rtc::scoped_refptr<I420BufferInterface> I210BufferBase::ToI420() {
224 rtc::scoped_refptr<I420Buffer> i420_buffer =
225 I420Buffer::Create(width(), height());
226 libyuv::I210ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(),
227 i420_buffer->MutableDataY(), i420_buffer->StrideY(),
228 i420_buffer->MutableDataU(), i420_buffer->StrideU(),
229 i420_buffer->MutableDataV(), i420_buffer->StrideV(),
230 width(), height());
231 return i420_buffer;
232 }
233
234 } // namespace
235
WrapI420Buffer(int width,int height,const uint8_t * y_plane,int y_stride,const uint8_t * u_plane,int u_stride,const uint8_t * v_plane,int v_stride,std::function<void ()> no_longer_used)236 rtc::scoped_refptr<I420BufferInterface> WrapI420Buffer(
237 int width,
238 int height,
239 const uint8_t* y_plane,
240 int y_stride,
241 const uint8_t* u_plane,
242 int u_stride,
243 const uint8_t* v_plane,
244 int v_stride,
245 std::function<void()> no_longer_used) {
246 return rtc::scoped_refptr<I420BufferInterface>(
247 rtc::make_ref_counted<WrappedYuvBuffer<I420BufferInterface>>(
248 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
249 v_stride, no_longer_used));
250 }
251
WrapI420ABuffer(int width,int height,const uint8_t * y_plane,int y_stride,const uint8_t * u_plane,int u_stride,const uint8_t * v_plane,int v_stride,const uint8_t * a_plane,int a_stride,std::function<void ()> no_longer_used)252 rtc::scoped_refptr<I420ABufferInterface> WrapI420ABuffer(
253 int width,
254 int height,
255 const uint8_t* y_plane,
256 int y_stride,
257 const uint8_t* u_plane,
258 int u_stride,
259 const uint8_t* v_plane,
260 int v_stride,
261 const uint8_t* a_plane,
262 int a_stride,
263 std::function<void()> no_longer_used) {
264 return rtc::scoped_refptr<I420ABufferInterface>(
265 rtc::make_ref_counted<WrappedYuvaBuffer<I420ABufferInterface>>(
266 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
267 v_stride, a_plane, a_stride, no_longer_used));
268 }
269
WrapI422Buffer(int width,int height,const uint8_t * y_plane,int y_stride,const uint8_t * u_plane,int u_stride,const uint8_t * v_plane,int v_stride,std::function<void ()> no_longer_used)270 rtc::scoped_refptr<I422BufferInterface> WrapI422Buffer(
271 int width,
272 int height,
273 const uint8_t* y_plane,
274 int y_stride,
275 const uint8_t* u_plane,
276 int u_stride,
277 const uint8_t* v_plane,
278 int v_stride,
279 std::function<void()> no_longer_used) {
280 return rtc::scoped_refptr<I422BufferBase>(
281 rtc::make_ref_counted<WrappedYuvBuffer<I422BufferBase>>(
282 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
283 v_stride, no_longer_used));
284 }
285
WrapI444Buffer(int width,int height,const uint8_t * y_plane,int y_stride,const uint8_t * u_plane,int u_stride,const uint8_t * v_plane,int v_stride,std::function<void ()> no_longer_used)286 rtc::scoped_refptr<I444BufferInterface> WrapI444Buffer(
287 int width,
288 int height,
289 const uint8_t* y_plane,
290 int y_stride,
291 const uint8_t* u_plane,
292 int u_stride,
293 const uint8_t* v_plane,
294 int v_stride,
295 std::function<void()> no_longer_used) {
296 return rtc::scoped_refptr<I444BufferInterface>(
297 rtc::make_ref_counted<WrappedYuvBuffer<I444BufferBase>>(
298 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
299 v_stride, no_longer_used));
300 }
301
WrapYuvBuffer(VideoFrameBuffer::Type type,int width,int height,const uint8_t * y_plane,int y_stride,const uint8_t * u_plane,int u_stride,const uint8_t * v_plane,int v_stride,std::function<void ()> no_longer_used)302 rtc::scoped_refptr<PlanarYuvBuffer> WrapYuvBuffer(
303 VideoFrameBuffer::Type type,
304 int width,
305 int height,
306 const uint8_t* y_plane,
307 int y_stride,
308 const uint8_t* u_plane,
309 int u_stride,
310 const uint8_t* v_plane,
311 int v_stride,
312 std::function<void()> no_longer_used) {
313 switch (type) {
314 case VideoFrameBuffer::Type::kI420:
315 return WrapI420Buffer(width, height, y_plane, y_stride, u_plane, u_stride,
316 v_plane, v_stride, no_longer_used);
317 case VideoFrameBuffer::Type::kI422:
318 return WrapI422Buffer(width, height, y_plane, y_stride, u_plane, u_stride,
319 v_plane, v_stride, no_longer_used);
320 case VideoFrameBuffer::Type::kI444:
321 return WrapI444Buffer(width, height, y_plane, y_stride, u_plane, u_stride,
322 v_plane, v_stride, no_longer_used);
323 default:
324 RTC_CHECK_NOTREACHED();
325 }
326 }
327
WrapI010Buffer(int width,int height,const uint16_t * y_plane,int y_stride,const uint16_t * u_plane,int u_stride,const uint16_t * v_plane,int v_stride,std::function<void ()> no_longer_used)328 rtc::scoped_refptr<I010BufferInterface> WrapI010Buffer(
329 int width,
330 int height,
331 const uint16_t* y_plane,
332 int y_stride,
333 const uint16_t* u_plane,
334 int u_stride,
335 const uint16_t* v_plane,
336 int v_stride,
337 std::function<void()> no_longer_used) {
338 return rtc::scoped_refptr<I010BufferInterface>(
339 rtc::make_ref_counted<WrappedYuv16BBuffer<I010BufferBase>>(
340 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
341 v_stride, no_longer_used));
342 }
343
WrapI210Buffer(int width,int height,const uint16_t * y_plane,int y_stride,const uint16_t * u_plane,int u_stride,const uint16_t * v_plane,int v_stride,std::function<void ()> no_longer_used)344 rtc::scoped_refptr<I210BufferInterface> WrapI210Buffer(
345 int width,
346 int height,
347 const uint16_t* y_plane,
348 int y_stride,
349 const uint16_t* u_plane,
350 int u_stride,
351 const uint16_t* v_plane,
352 int v_stride,
353 std::function<void()> no_longer_used) {
354 return rtc::scoped_refptr<I210BufferInterface>(
355 rtc::make_ref_counted<WrappedYuv16BBuffer<I210BufferBase>>(
356 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
357 v_stride, no_longer_used));
358 }
359
360 } // namespace webrtc
361