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/video/i420_buffer.h"
13 #include "rtc_base/checks.h"
14 #include "rtc_base/ref_counted_object.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,const rtc::Callback0<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 const rtc::Callback0<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 rtc::Callback0<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,const rtc::Callback0<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 const rtc::Callback0<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 // Template to implement a wrapped buffer for a PlanarYuv16BBuffer.
128 template <typename Base>
129 class WrappedYuv16BBuffer : public Base {
130 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,const rtc::Callback0<void> & no_longer_used)131 WrappedYuv16BBuffer(int width,
132 int height,
133 const uint16_t* y_plane,
134 int y_stride,
135 const uint16_t* u_plane,
136 int u_stride,
137 const uint16_t* v_plane,
138 int v_stride,
139 const rtc::Callback0<void>& no_longer_used)
140 : width_(width),
141 height_(height),
142 y_plane_(y_plane),
143 u_plane_(u_plane),
144 v_plane_(v_plane),
145 y_stride_(y_stride),
146 u_stride_(u_stride),
147 v_stride_(v_stride),
148 no_longer_used_cb_(no_longer_used) {}
149
~WrappedYuv16BBuffer()150 ~WrappedYuv16BBuffer() override { no_longer_used_cb_(); }
151
width() const152 int width() const override { return width_; }
153
height() const154 int height() const override { return height_; }
155
DataY() const156 const uint16_t* DataY() const override { return y_plane_; }
157
DataU() const158 const uint16_t* DataU() const override { return u_plane_; }
159
DataV() const160 const uint16_t* DataV() const override { return v_plane_; }
161
StrideY() const162 int StrideY() const override { return y_stride_; }
163
StrideU() const164 int StrideU() const override { return u_stride_; }
165
StrideV() const166 int StrideV() const override { return v_stride_; }
167
168 private:
169 friend class rtc::RefCountedObject<WrappedYuv16BBuffer>;
170
171 const int width_;
172 const int height_;
173 const uint16_t* const y_plane_;
174 const uint16_t* const u_plane_;
175 const uint16_t* const v_plane_;
176 const int y_stride_;
177 const int u_stride_;
178 const int v_stride_;
179 rtc::Callback0<void> no_longer_used_cb_;
180 };
181
182 class I010BufferBase : public I010BufferInterface {
183 public:
184 rtc::scoped_refptr<I420BufferInterface> ToI420() final;
185 };
186
ToI420()187 rtc::scoped_refptr<I420BufferInterface> I010BufferBase::ToI420() {
188 rtc::scoped_refptr<I420Buffer> i420_buffer =
189 I420Buffer::Create(width(), height());
190 #if 0
191 libyuv::I010ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(),
192 i420_buffer->MutableDataY(), i420_buffer->StrideY(),
193 i420_buffer->MutableDataU(), i420_buffer->StrideU(),
194 i420_buffer->MutableDataV(), i420_buffer->StrideV(),
195 width(), height());
196 #else
197 abort();
198 #endif
199 return i420_buffer;
200 }
201
202 } // namespace
203
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,const rtc::Callback0<void> & no_longer_used)204 rtc::scoped_refptr<I420BufferInterface> WrapI420Buffer(
205 int width,
206 int height,
207 const uint8_t* y_plane,
208 int y_stride,
209 const uint8_t* u_plane,
210 int u_stride,
211 const uint8_t* v_plane,
212 int v_stride,
213 const rtc::Callback0<void>& no_longer_used) {
214 return rtc::scoped_refptr<I420BufferInterface>(
215 new rtc::RefCountedObject<WrappedYuvBuffer<I420BufferInterface>>(
216 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
217 v_stride, no_longer_used));
218 }
219
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,const rtc::Callback0<void> & no_longer_used)220 rtc::scoped_refptr<I420ABufferInterface> WrapI420ABuffer(
221 int width,
222 int height,
223 const uint8_t* y_plane,
224 int y_stride,
225 const uint8_t* u_plane,
226 int u_stride,
227 const uint8_t* v_plane,
228 int v_stride,
229 const uint8_t* a_plane,
230 int a_stride,
231 const rtc::Callback0<void>& no_longer_used) {
232 return rtc::scoped_refptr<I420ABufferInterface>(
233 new rtc::RefCountedObject<WrappedYuvaBuffer<I420ABufferInterface>>(
234 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
235 v_stride, a_plane, a_stride, no_longer_used));
236 }
237
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,const rtc::Callback0<void> & no_longer_used)238 rtc::scoped_refptr<I444BufferInterface> WrapI444Buffer(
239 int width,
240 int height,
241 const uint8_t* y_plane,
242 int y_stride,
243 const uint8_t* u_plane,
244 int u_stride,
245 const uint8_t* v_plane,
246 int v_stride,
247 const rtc::Callback0<void>& no_longer_used) {
248 return rtc::scoped_refptr<I444BufferInterface>(
249 new rtc::RefCountedObject<WrappedYuvBuffer<I444BufferBase>>(
250 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
251 v_stride, no_longer_used));
252 }
253
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,const rtc::Callback0<void> & no_longer_used)254 rtc::scoped_refptr<PlanarYuvBuffer> WrapYuvBuffer(
255 VideoFrameBuffer::Type type,
256 int width,
257 int height,
258 const uint8_t* y_plane,
259 int y_stride,
260 const uint8_t* u_plane,
261 int u_stride,
262 const uint8_t* v_plane,
263 int v_stride,
264 const rtc::Callback0<void>& no_longer_used) {
265 switch (type) {
266 case VideoFrameBuffer::Type::kI420:
267 return WrapI420Buffer(width, height, y_plane, y_stride, u_plane, u_stride,
268 v_plane, v_stride, no_longer_used);
269 case VideoFrameBuffer::Type::kI444:
270 return WrapI444Buffer(width, height, y_plane, y_stride, u_plane, u_stride,
271 v_plane, v_stride, no_longer_used);
272 default:
273 FATAL() << "Unexpected frame buffer type.";
274 return nullptr;
275 }
276 }
277
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,const rtc::Callback0<void> & no_longer_used)278 rtc::scoped_refptr<I010BufferInterface> WrapI010Buffer(
279 int width,
280 int height,
281 const uint16_t* y_plane,
282 int y_stride,
283 const uint16_t* u_plane,
284 int u_stride,
285 const uint16_t* v_plane,
286 int v_stride,
287 const rtc::Callback0<void>& no_longer_used) {
288 return rtc::scoped_refptr<I010BufferInterface>(
289 new rtc::RefCountedObject<WrappedYuv16BBuffer<I010BufferBase>>(
290 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
291 v_stride, no_longer_used));
292 }
293
294 } // namespace webrtc
295