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