blob: eeb77a2bbdb627efc2f4d2d70f38eda7d659138a [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
12#include <string.h>
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +000013
Niels Möller718a7632016-06-13 13:06:01 +020014#include <algorithm>
15
Patrik Höglundb5b5bce2017-11-13 10:19:58 +010016#include "api/video/i420_buffer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "rtc_base/checks.h"
18#include "rtc_base/keep_ref_until_done.h"
Mirko Bonadei65432062017-12-11 09:32:13 +010019#include "third_party/libyuv/include/libyuv/convert.h"
20#include "third_party/libyuv/include/libyuv/planar_functions.h"
21#include "third_party/libyuv/include/libyuv/scale.h"
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +000022
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +000023namespace webrtc {
24
Patrik Höglundb5b5bce2017-11-13 10:19:58 +010025namespace {
Per33544192015-04-02 12:30:51 +020026
yuweih23cc4682017-06-22 20:28:06 -070027// Template to implement a wrapped buffer for a I4??BufferInterface.
28template <typename Base>
29class WrappedYuvBuffer : public Base {
30 public:
31 WrappedYuvBuffer(int width,
32 int height,
33 const uint8_t* y_plane,
34 int y_stride,
35 const uint8_t* u_plane,
36 int u_stride,
37 const uint8_t* v_plane,
38 int v_stride,
39 const rtc::Callback0<void>& no_longer_used)
40 : width_(width),
41 height_(height),
42 y_plane_(y_plane),
43 u_plane_(u_plane),
44 v_plane_(v_plane),
45 y_stride_(y_stride),
46 u_stride_(u_stride),
47 v_stride_(v_stride),
48 no_longer_used_cb_(no_longer_used) {}
49
Emircan Uysaler574eaa42017-11-09 12:33:24 -080050 ~WrappedYuvBuffer() override { no_longer_used_cb_(); }
51
yuweih23cc4682017-06-22 20:28:06 -070052 int width() const override { return width_; }
53
54 int height() const override { return height_; }
55
56 const uint8_t* DataY() const override { return y_plane_; }
57
58 const uint8_t* DataU() const override { return u_plane_; }
59
60 const uint8_t* DataV() const override { return v_plane_; }
61
62 int StrideY() const override { return y_stride_; }
63
64 int StrideU() const override { return u_stride_; }
65
66 int StrideV() const override { return v_stride_; }
67
68 private:
69 friend class rtc::RefCountedObject<WrappedYuvBuffer>;
70
yuweih23cc4682017-06-22 20:28:06 -070071 const int width_;
72 const int height_;
73 const uint8_t* const y_plane_;
74 const uint8_t* const u_plane_;
75 const uint8_t* const v_plane_;
76 const int y_stride_;
77 const int u_stride_;
78 const int v_stride_;
79 rtc::Callback0<void> no_longer_used_cb_;
80};
81
Emircan Uysaler574eaa42017-11-09 12:33:24 -080082// Template to implement a wrapped buffer for a I4??BufferInterface.
83template <typename BaseWithA>
84class WrappedYuvaBuffer : public WrappedYuvBuffer<BaseWithA> {
85 public:
86 WrappedYuvaBuffer(int width,
87 int height,
88 const uint8_t* y_plane,
89 int y_stride,
90 const uint8_t* u_plane,
91 int u_stride,
92 const uint8_t* v_plane,
93 int v_stride,
94 const uint8_t* a_plane,
95 int a_stride,
96 const rtc::Callback0<void>& no_longer_used)
97 : WrappedYuvBuffer<BaseWithA>(width,
98 height,
99 y_plane,
100 y_stride,
101 u_plane,
102 u_stride,
103 v_plane,
104 v_stride,
105 no_longer_used),
106 a_plane_(a_plane),
107 a_stride_(a_stride) {}
108
109 const uint8_t* DataA() const override { return a_plane_; }
110 int StrideA() const override { return a_stride_; }
111
112 private:
113 const uint8_t* const a_plane_;
114 const int a_stride_;
115};
116
Patrik Höglundb5b5bce2017-11-13 10:19:58 +0100117class I444BufferBase : public I444BufferInterface {
118 public:
119 rtc::scoped_refptr<I420BufferInterface> ToI420() final;
120};
121
122rtc::scoped_refptr<I420BufferInterface> I444BufferBase::ToI420() {
123 rtc::scoped_refptr<I420Buffer> i420_buffer =
124 I420Buffer::Create(width(), height());
125 libyuv::I444ToI420(DataY(), StrideY(), DataU(), StrideU(), DataV(), StrideV(),
126 i420_buffer->MutableDataY(), i420_buffer->StrideY(),
127 i420_buffer->MutableDataU(), i420_buffer->StrideU(),
128 i420_buffer->MutableDataV(), i420_buffer->StrideV(),
129 width(), height());
130 return i420_buffer;
131}
132
133} // namespace
134
135WrappedI420Buffer::WrappedI420Buffer(int width,
136 int height,
137 const uint8_t* y_plane,
138 int y_stride,
139 const uint8_t* u_plane,
140 int u_stride,
141 const uint8_t* v_plane,
142 int v_stride,
143 const rtc::Callback0<void>& no_longer_used)
144 : width_(width),
145 height_(height),
146 y_plane_(y_plane),
147 u_plane_(u_plane),
148 v_plane_(v_plane),
149 y_stride_(y_stride),
150 u_stride_(u_stride),
151 v_stride_(v_stride),
Yves Gerey665174f2018-06-19 15:03:05 +0200152 no_longer_used_cb_(no_longer_used) {}
Patrik Höglundb5b5bce2017-11-13 10:19:58 +0100153
154WrappedI420Buffer::~WrappedI420Buffer() {
155 no_longer_used_cb_();
156}
157
158int WrappedI420Buffer::width() const {
159 return width_;
160}
161
162int WrappedI420Buffer::height() const {
163 return height_;
164}
165
166const uint8_t* WrappedI420Buffer::DataY() const {
167 return y_plane_;
168}
169const uint8_t* WrappedI420Buffer::DataU() const {
170 return u_plane_;
171}
172const uint8_t* WrappedI420Buffer::DataV() const {
173 return v_plane_;
174}
175
176int WrappedI420Buffer::StrideY() const {
177 return y_stride_;
178}
179int WrappedI420Buffer::StrideU() const {
180 return u_stride_;
181}
182int WrappedI420Buffer::StrideV() const {
183 return v_stride_;
184}
185
yuweih23cc4682017-06-22 20:28:06 -0700186rtc::scoped_refptr<I420BufferInterface> WrapI420Buffer(
187 int width,
188 int height,
189 const uint8_t* y_plane,
190 int y_stride,
191 const uint8_t* u_plane,
192 int u_stride,
193 const uint8_t* v_plane,
194 int v_stride,
195 const rtc::Callback0<void>& no_longer_used) {
196 return rtc::scoped_refptr<I420BufferInterface>(
197 new rtc::RefCountedObject<WrappedYuvBuffer<I420BufferInterface>>(
198 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
199 v_stride, no_longer_used));
200}
201
Emircan Uysaler574eaa42017-11-09 12:33:24 -0800202rtc::scoped_refptr<I420ABufferInterface> WrapI420ABuffer(
203 int width,
204 int height,
205 const uint8_t* y_plane,
206 int y_stride,
207 const uint8_t* u_plane,
208 int u_stride,
209 const uint8_t* v_plane,
210 int v_stride,
211 const uint8_t* a_plane,
212 int a_stride,
213 const rtc::Callback0<void>& no_longer_used) {
214 return rtc::scoped_refptr<I420ABufferInterface>(
215 new rtc::RefCountedObject<WrappedYuvaBuffer<I420ABufferInterface>>(
216 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
217 v_stride, a_plane, a_stride, no_longer_used));
218}
219
yuweih23cc4682017-06-22 20:28:06 -0700220rtc::scoped_refptr<I444BufferInterface> WrapI444Buffer(
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 rtc::Callback0<void>& no_longer_used) {
230 return rtc::scoped_refptr<I444BufferInterface>(
Patrik Höglundb5b5bce2017-11-13 10:19:58 +0100231 new rtc::RefCountedObject<WrappedYuvBuffer<I444BufferBase>>(
yuweih23cc4682017-06-22 20:28:06 -0700232 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
233 v_stride, no_longer_used));
234}
235
236rtc::scoped_refptr<PlanarYuvBuffer> WrapYuvBuffer(
237 VideoFrameBuffer::Type type,
238 int width,
239 int height,
240 const uint8_t* y_plane,
241 int y_stride,
242 const uint8_t* u_plane,
243 int u_stride,
244 const uint8_t* v_plane,
245 int v_stride,
246 const rtc::Callback0<void>& no_longer_used) {
247 switch (type) {
248 case VideoFrameBuffer::Type::kI420:
249 return WrapI420Buffer(width, height, y_plane, y_stride, u_plane, u_stride,
250 v_plane, v_stride, no_longer_used);
251 case VideoFrameBuffer::Type::kI444:
252 return WrapI444Buffer(width, height, y_plane, y_stride, u_plane, u_stride,
253 v_plane, v_stride, no_longer_used);
254 default:
255 FATAL() << "Unexpected frame buffer type.";
256 return nullptr;
257 }
258}
259
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +0000260} // namespace webrtc