xref: /aosp_15_r20/external/webrtc/common_video/video_frame_buffer.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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