blob: 823c5ad7a118b9ac9dee74b1d3d9478b9ab4dbdb [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
Patrik Höglundb5b5bce2017-11-13 10:19:58 +010012#include "api/video/i420_buffer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "rtc_base/checks.h"
Steve Anton10542f22019-01-11 09:11:00 -080014#include "rtc_base/ref_counted_object.h"
Mirko Bonadei65432062017-12-11 09:32:13 +010015#include "third_party/libyuv/include/libyuv/convert.h"
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +000016
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +000017namespace webrtc {
18
Patrik Höglundb5b5bce2017-11-13 10:19:58 +010019namespace {
Per33544192015-04-02 12:30:51 +020020
yuweih23cc4682017-06-22 20:28:06 -070021// Template to implement a wrapped buffer for a I4??BufferInterface.
22template <typename Base>
23class WrappedYuvBuffer : public Base {
24 public:
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
Emircan Uysaler574eaa42017-11-09 12:33:24 -080044 ~WrappedYuvBuffer() override { no_longer_used_cb_(); }
45
yuweih23cc4682017-06-22 20:28:06 -070046 int width() const override { return width_; }
47
48 int height() const override { return height_; }
49
50 const uint8_t* DataY() const override { return y_plane_; }
51
52 const uint8_t* DataU() const override { return u_plane_; }
53
54 const uint8_t* DataV() const override { return v_plane_; }
55
56 int StrideY() const override { return y_stride_; }
57
58 int StrideU() const override { return u_stride_; }
59
60 int StrideV() const override { return v_stride_; }
61
62 private:
63 friend class rtc::RefCountedObject<WrappedYuvBuffer>;
64
yuweih23cc4682017-06-22 20:28:06 -070065 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
Emircan Uysaler574eaa42017-11-09 12:33:24 -080076// Template to implement a wrapped buffer for a I4??BufferInterface.
77template <typename BaseWithA>
78class WrappedYuvaBuffer : public WrappedYuvBuffer<BaseWithA> {
79 public:
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
103 const uint8_t* DataA() const override { return a_plane_; }
104 int StrideA() const override { return a_stride_; }
105
106 private:
107 const uint8_t* const a_plane_;
108 const int a_stride_;
109};
110
Patrik Höglundb5b5bce2017-11-13 10:19:58 +0100111class I444BufferBase : public I444BufferInterface {
112 public:
113 rtc::scoped_refptr<I420BufferInterface> ToI420() final;
114};
115
116rtc::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
Emircan Uysaler901e0ff2018-06-26 12:22:38 -0700127// Template to implement a wrapped buffer for a PlanarYuv16BBuffer.
128template <typename Base>
129class WrappedYuv16BBuffer : public Base {
130 public:
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
150 ~WrappedYuv16BBuffer() override { no_longer_used_cb_(); }
151
152 int width() const override { return width_; }
153
154 int height() const override { return height_; }
155
156 const uint16_t* DataY() const override { return y_plane_; }
157
158 const uint16_t* DataU() const override { return u_plane_; }
159
160 const uint16_t* DataV() const override { return v_plane_; }
161
162 int StrideY() const override { return y_stride_; }
163
164 int StrideU() const override { return u_stride_; }
165
166 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
182class I010BufferBase : public I010BufferInterface {
183 public:
184 rtc::scoped_refptr<I420BufferInterface> ToI420() final;
185};
186
187rtc::scoped_refptr<I420BufferInterface> I010BufferBase::ToI420() {
188 rtc::scoped_refptr<I420Buffer> i420_buffer =
189 I420Buffer::Create(width(), height());
190 libyuv::I010ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(),
191 i420_buffer->MutableDataY(), i420_buffer->StrideY(),
192 i420_buffer->MutableDataU(), i420_buffer->StrideU(),
193 i420_buffer->MutableDataV(), i420_buffer->StrideV(),
194 width(), height());
195 return i420_buffer;
196}
197
Patrik Höglundb5b5bce2017-11-13 10:19:58 +0100198} // namespace
199
yuweih23cc4682017-06-22 20:28:06 -0700200rtc::scoped_refptr<I420BufferInterface> WrapI420Buffer(
201 int width,
202 int height,
203 const uint8_t* y_plane,
204 int y_stride,
205 const uint8_t* u_plane,
206 int u_stride,
207 const uint8_t* v_plane,
208 int v_stride,
209 const rtc::Callback0<void>& no_longer_used) {
210 return rtc::scoped_refptr<I420BufferInterface>(
211 new rtc::RefCountedObject<WrappedYuvBuffer<I420BufferInterface>>(
212 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
213 v_stride, no_longer_used));
214}
215
Emircan Uysaler574eaa42017-11-09 12:33:24 -0800216rtc::scoped_refptr<I420ABufferInterface> WrapI420ABuffer(
217 int width,
218 int height,
219 const uint8_t* y_plane,
220 int y_stride,
221 const uint8_t* u_plane,
222 int u_stride,
223 const uint8_t* v_plane,
224 int v_stride,
225 const uint8_t* a_plane,
226 int a_stride,
227 const rtc::Callback0<void>& no_longer_used) {
228 return rtc::scoped_refptr<I420ABufferInterface>(
229 new rtc::RefCountedObject<WrappedYuvaBuffer<I420ABufferInterface>>(
230 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
231 v_stride, a_plane, a_stride, no_longer_used));
232}
233
yuweih23cc4682017-06-22 20:28:06 -0700234rtc::scoped_refptr<I444BufferInterface> WrapI444Buffer(
235 int width,
236 int height,
237 const uint8_t* y_plane,
238 int y_stride,
239 const uint8_t* u_plane,
240 int u_stride,
241 const uint8_t* v_plane,
242 int v_stride,
243 const rtc::Callback0<void>& no_longer_used) {
244 return rtc::scoped_refptr<I444BufferInterface>(
Patrik Höglundb5b5bce2017-11-13 10:19:58 +0100245 new rtc::RefCountedObject<WrappedYuvBuffer<I444BufferBase>>(
yuweih23cc4682017-06-22 20:28:06 -0700246 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
247 v_stride, no_longer_used));
248}
249
250rtc::scoped_refptr<PlanarYuvBuffer> WrapYuvBuffer(
251 VideoFrameBuffer::Type type,
252 int width,
253 int height,
254 const uint8_t* y_plane,
255 int y_stride,
256 const uint8_t* u_plane,
257 int u_stride,
258 const uint8_t* v_plane,
259 int v_stride,
260 const rtc::Callback0<void>& no_longer_used) {
261 switch (type) {
262 case VideoFrameBuffer::Type::kI420:
263 return WrapI420Buffer(width, height, y_plane, y_stride, u_plane, u_stride,
264 v_plane, v_stride, no_longer_used);
265 case VideoFrameBuffer::Type::kI444:
266 return WrapI444Buffer(width, height, y_plane, y_stride, u_plane, u_stride,
267 v_plane, v_stride, no_longer_used);
268 default:
269 FATAL() << "Unexpected frame buffer type.";
270 return nullptr;
271 }
272}
273
Emircan Uysaler901e0ff2018-06-26 12:22:38 -0700274rtc::scoped_refptr<I010BufferInterface> WrapI010Buffer(
275 int width,
276 int height,
277 const uint16_t* y_plane,
278 int y_stride,
279 const uint16_t* u_plane,
280 int u_stride,
281 const uint16_t* v_plane,
282 int v_stride,
283 const rtc::Callback0<void>& no_longer_used) {
284 return rtc::scoped_refptr<I010BufferInterface>(
285 new rtc::RefCountedObject<WrappedYuv16BBuffer<I010BufferBase>>(
286 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
287 v_stride, no_longer_used));
288}
289
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +0000290} // namespace webrtc