blob: 6b772d64b887b522f9fbe2483dacd6e527e6de30 [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),
152 no_longer_used_cb_(no_longer_used) {
153}
154
155WrappedI420Buffer::~WrappedI420Buffer() {
156 no_longer_used_cb_();
157}
158
159int WrappedI420Buffer::width() const {
160 return width_;
161}
162
163int WrappedI420Buffer::height() const {
164 return height_;
165}
166
167const uint8_t* WrappedI420Buffer::DataY() const {
168 return y_plane_;
169}
170const uint8_t* WrappedI420Buffer::DataU() const {
171 return u_plane_;
172}
173const uint8_t* WrappedI420Buffer::DataV() const {
174 return v_plane_;
175}
176
177int WrappedI420Buffer::StrideY() const {
178 return y_stride_;
179}
180int WrappedI420Buffer::StrideU() const {
181 return u_stride_;
182}
183int WrappedI420Buffer::StrideV() const {
184 return v_stride_;
185}
186
yuweih23cc4682017-06-22 20:28:06 -0700187rtc::scoped_refptr<I420BufferInterface> WrapI420Buffer(
188 int width,
189 int height,
190 const uint8_t* y_plane,
191 int y_stride,
192 const uint8_t* u_plane,
193 int u_stride,
194 const uint8_t* v_plane,
195 int v_stride,
196 const rtc::Callback0<void>& no_longer_used) {
197 return rtc::scoped_refptr<I420BufferInterface>(
198 new rtc::RefCountedObject<WrappedYuvBuffer<I420BufferInterface>>(
199 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
200 v_stride, no_longer_used));
201}
202
Emircan Uysaler574eaa42017-11-09 12:33:24 -0800203rtc::scoped_refptr<I420ABufferInterface> WrapI420ABuffer(
204 int width,
205 int height,
206 const uint8_t* y_plane,
207 int y_stride,
208 const uint8_t* u_plane,
209 int u_stride,
210 const uint8_t* v_plane,
211 int v_stride,
212 const uint8_t* a_plane,
213 int a_stride,
214 const rtc::Callback0<void>& no_longer_used) {
215 return rtc::scoped_refptr<I420ABufferInterface>(
216 new rtc::RefCountedObject<WrappedYuvaBuffer<I420ABufferInterface>>(
217 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
218 v_stride, a_plane, a_stride, no_longer_used));
219}
220
yuweih23cc4682017-06-22 20:28:06 -0700221rtc::scoped_refptr<I444BufferInterface> WrapI444Buffer(
222 int width,
223 int height,
224 const uint8_t* y_plane,
225 int y_stride,
226 const uint8_t* u_plane,
227 int u_stride,
228 const uint8_t* v_plane,
229 int v_stride,
230 const rtc::Callback0<void>& no_longer_used) {
231 return rtc::scoped_refptr<I444BufferInterface>(
Patrik Höglundb5b5bce2017-11-13 10:19:58 +0100232 new rtc::RefCountedObject<WrappedYuvBuffer<I444BufferBase>>(
yuweih23cc4682017-06-22 20:28:06 -0700233 width, height, y_plane, y_stride, u_plane, u_stride, v_plane,
234 v_stride, no_longer_used));
235}
236
237rtc::scoped_refptr<PlanarYuvBuffer> WrapYuvBuffer(
238 VideoFrameBuffer::Type type,
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 switch (type) {
249 case VideoFrameBuffer::Type::kI420:
250 return WrapI420Buffer(width, height, y_plane, y_stride, u_plane, u_stride,
251 v_plane, v_stride, no_longer_used);
252 case VideoFrameBuffer::Type::kI444:
253 return WrapI444Buffer(width, height, y_plane, y_stride, u_plane, u_stride,
254 v_plane, v_stride, no_longer_used);
255 default:
256 FATAL() << "Unexpected frame buffer type.";
257 return nullptr;
258 }
259}
260
magjed@webrtc.org2386d6d2015-03-05 14:03:08 +0000261} // namespace webrtc