|
1 /* |
|
2 * Copyright 2012 The LibYuv 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 |
|
11 #include "libyuv/convert_from.h" |
|
12 |
|
13 #include "libyuv/basic_types.h" |
|
14 #include "libyuv/convert.h" // For I420Copy |
|
15 #include "libyuv/cpu_id.h" |
|
16 #include "libyuv/format_conversion.h" |
|
17 #include "libyuv/planar_functions.h" |
|
18 #include "libyuv/rotate.h" |
|
19 #include "libyuv/scale.h" // For ScalePlane() |
|
20 #include "libyuv/video_common.h" |
|
21 #include "libyuv/row.h" |
|
22 |
|
23 #ifdef __cplusplus |
|
24 namespace libyuv { |
|
25 extern "C" { |
|
26 #endif |
|
27 |
|
28 #define SUBSAMPLE(v, a, s) (v < 0) ? (-((-v + a) >> s)) : ((v + a) >> s) |
|
29 static __inline int Abs(int v) { |
|
30 return v >= 0 ? v : -v; |
|
31 } |
|
32 |
|
33 // I420 To any I4xx YUV format with mirroring. |
|
34 static int I420ToI4xx(const uint8* src_y, int src_stride_y, |
|
35 const uint8* src_u, int src_stride_u, |
|
36 const uint8* src_v, int src_stride_v, |
|
37 uint8* dst_y, int dst_stride_y, |
|
38 uint8* dst_u, int dst_stride_u, |
|
39 uint8* dst_v, int dst_stride_v, |
|
40 int src_y_width, int src_y_height, |
|
41 int dst_uv_width, int dst_uv_height) { |
|
42 if (src_y_width == 0 || src_y_height == 0 || |
|
43 dst_uv_width <= 0 || dst_uv_height <= 0) { |
|
44 return -1; |
|
45 } |
|
46 const int dst_y_width = Abs(src_y_width); |
|
47 const int dst_y_height = Abs(src_y_height); |
|
48 const int src_uv_width = SUBSAMPLE(src_y_width, 1, 1); |
|
49 const int src_uv_height = SUBSAMPLE(src_y_height, 1, 1); |
|
50 ScalePlane(src_y, src_stride_y, src_y_width, src_y_height, |
|
51 dst_y, dst_stride_y, dst_y_width, dst_y_height, |
|
52 kFilterBilinear); |
|
53 ScalePlane(src_u, src_stride_u, src_uv_width, src_uv_height, |
|
54 dst_u, dst_stride_u, dst_uv_width, dst_uv_height, |
|
55 kFilterBilinear); |
|
56 ScalePlane(src_v, src_stride_v, src_uv_width, src_uv_height, |
|
57 dst_v, dst_stride_v, dst_uv_width, dst_uv_height, |
|
58 kFilterBilinear); |
|
59 return 0; |
|
60 } |
|
61 |
|
62 // 420 chroma is 1/2 width, 1/2 height |
|
63 // 422 chroma is 1/2 width, 1x height |
|
64 LIBYUV_API |
|
65 int I420ToI422(const uint8* src_y, int src_stride_y, |
|
66 const uint8* src_u, int src_stride_u, |
|
67 const uint8* src_v, int src_stride_v, |
|
68 uint8* dst_y, int dst_stride_y, |
|
69 uint8* dst_u, int dst_stride_u, |
|
70 uint8* dst_v, int dst_stride_v, |
|
71 int width, int height) { |
|
72 const int dst_uv_width = (Abs(width) + 1) >> 1; |
|
73 const int dst_uv_height = Abs(height); |
|
74 return I420ToI4xx(src_y, src_stride_y, |
|
75 src_u, src_stride_u, |
|
76 src_v, src_stride_v, |
|
77 dst_y, dst_stride_y, |
|
78 dst_u, dst_stride_u, |
|
79 dst_v, dst_stride_v, |
|
80 width, height, |
|
81 dst_uv_width, dst_uv_height); |
|
82 } |
|
83 |
|
84 // 420 chroma is 1/2 width, 1/2 height |
|
85 // 444 chroma is 1x width, 1x height |
|
86 LIBYUV_API |
|
87 int I420ToI444(const uint8* src_y, int src_stride_y, |
|
88 const uint8* src_u, int src_stride_u, |
|
89 const uint8* src_v, int src_stride_v, |
|
90 uint8* dst_y, int dst_stride_y, |
|
91 uint8* dst_u, int dst_stride_u, |
|
92 uint8* dst_v, int dst_stride_v, |
|
93 int width, int height) { |
|
94 const int dst_uv_width = Abs(width); |
|
95 const int dst_uv_height = Abs(height); |
|
96 return I420ToI4xx(src_y, src_stride_y, |
|
97 src_u, src_stride_u, |
|
98 src_v, src_stride_v, |
|
99 dst_y, dst_stride_y, |
|
100 dst_u, dst_stride_u, |
|
101 dst_v, dst_stride_v, |
|
102 width, height, |
|
103 dst_uv_width, dst_uv_height); |
|
104 } |
|
105 |
|
106 // 420 chroma is 1/2 width, 1/2 height |
|
107 // 411 chroma is 1/4 width, 1x height |
|
108 LIBYUV_API |
|
109 int I420ToI411(const uint8* src_y, int src_stride_y, |
|
110 const uint8* src_u, int src_stride_u, |
|
111 const uint8* src_v, int src_stride_v, |
|
112 uint8* dst_y, int dst_stride_y, |
|
113 uint8* dst_u, int dst_stride_u, |
|
114 uint8* dst_v, int dst_stride_v, |
|
115 int width, int height) { |
|
116 const int dst_uv_width = (Abs(width) + 3) >> 2; |
|
117 const int dst_uv_height = Abs(height); |
|
118 return I420ToI4xx(src_y, src_stride_y, |
|
119 src_u, src_stride_u, |
|
120 src_v, src_stride_v, |
|
121 dst_y, dst_stride_y, |
|
122 dst_u, dst_stride_u, |
|
123 dst_v, dst_stride_v, |
|
124 width, height, |
|
125 dst_uv_width, dst_uv_height); |
|
126 } |
|
127 |
|
128 // Copy to I400. Source can be I420,422,444,400,NV12,NV21 |
|
129 LIBYUV_API |
|
130 int I400Copy(const uint8* src_y, int src_stride_y, |
|
131 uint8* dst_y, int dst_stride_y, |
|
132 int width, int height) { |
|
133 if (!src_y || !dst_y || |
|
134 width <= 0 || height == 0) { |
|
135 return -1; |
|
136 } |
|
137 // Negative height means invert the image. |
|
138 if (height < 0) { |
|
139 height = -height; |
|
140 src_y = src_y + (height - 1) * src_stride_y; |
|
141 src_stride_y = -src_stride_y; |
|
142 } |
|
143 CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); |
|
144 return 0; |
|
145 } |
|
146 |
|
147 LIBYUV_API |
|
148 int I422ToYUY2(const uint8* src_y, int src_stride_y, |
|
149 const uint8* src_u, int src_stride_u, |
|
150 const uint8* src_v, int src_stride_v, |
|
151 uint8* dst_yuy2, int dst_stride_yuy2, |
|
152 int width, int height) { |
|
153 if (!src_y || !src_u || !src_v || !dst_yuy2 || |
|
154 width <= 0 || height == 0) { |
|
155 return -1; |
|
156 } |
|
157 // Negative height means invert the image. |
|
158 if (height < 0) { |
|
159 height = -height; |
|
160 dst_yuy2 = dst_yuy2 + (height - 1) * dst_stride_yuy2; |
|
161 dst_stride_yuy2 = -dst_stride_yuy2; |
|
162 } |
|
163 // Coalesce rows. |
|
164 if (src_stride_y == width && |
|
165 src_stride_u * 2 == width && |
|
166 src_stride_v * 2 == width && |
|
167 dst_stride_yuy2 == width * 2) { |
|
168 width *= height; |
|
169 height = 1; |
|
170 src_stride_y = src_stride_u = src_stride_v = dst_stride_yuy2 = 0; |
|
171 } |
|
172 void (*I422ToYUY2Row)(const uint8* src_y, const uint8* src_u, |
|
173 const uint8* src_v, uint8* dst_yuy2, int width) = |
|
174 I422ToYUY2Row_C; |
|
175 #if defined(HAS_I422TOYUY2ROW_SSE2) |
|
176 if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { |
|
177 I422ToYUY2Row = I422ToYUY2Row_Any_SSE2; |
|
178 if (IS_ALIGNED(width, 16)) { |
|
179 I422ToYUY2Row = I422ToYUY2Row_SSE2; |
|
180 } |
|
181 } |
|
182 #elif defined(HAS_I422TOYUY2ROW_NEON) |
|
183 if (TestCpuFlag(kCpuHasNEON) && width >= 16) { |
|
184 I422ToYUY2Row = I422ToYUY2Row_Any_NEON; |
|
185 if (IS_ALIGNED(width, 16)) { |
|
186 I422ToYUY2Row = I422ToYUY2Row_NEON; |
|
187 } |
|
188 } |
|
189 #endif |
|
190 |
|
191 for (int y = 0; y < height; ++y) { |
|
192 I422ToYUY2Row(src_y, src_u, src_v, dst_yuy2, width); |
|
193 src_y += src_stride_y; |
|
194 src_u += src_stride_u; |
|
195 src_v += src_stride_v; |
|
196 dst_yuy2 += dst_stride_yuy2; |
|
197 } |
|
198 return 0; |
|
199 } |
|
200 |
|
201 LIBYUV_API |
|
202 int I420ToYUY2(const uint8* src_y, int src_stride_y, |
|
203 const uint8* src_u, int src_stride_u, |
|
204 const uint8* src_v, int src_stride_v, |
|
205 uint8* dst_yuy2, int dst_stride_yuy2, |
|
206 int width, int height) { |
|
207 if (!src_y || !src_u || !src_v || !dst_yuy2 || |
|
208 width <= 0 || height == 0) { |
|
209 return -1; |
|
210 } |
|
211 // Negative height means invert the image. |
|
212 if (height < 0) { |
|
213 height = -height; |
|
214 dst_yuy2 = dst_yuy2 + (height - 1) * dst_stride_yuy2; |
|
215 dst_stride_yuy2 = -dst_stride_yuy2; |
|
216 } |
|
217 void (*I422ToYUY2Row)(const uint8* src_y, const uint8* src_u, |
|
218 const uint8* src_v, uint8* dst_yuy2, int width) = |
|
219 I422ToYUY2Row_C; |
|
220 #if defined(HAS_I422TOYUY2ROW_SSE2) |
|
221 if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { |
|
222 I422ToYUY2Row = I422ToYUY2Row_Any_SSE2; |
|
223 if (IS_ALIGNED(width, 16)) { |
|
224 I422ToYUY2Row = I422ToYUY2Row_SSE2; |
|
225 } |
|
226 } |
|
227 #elif defined(HAS_I422TOYUY2ROW_NEON) |
|
228 if (TestCpuFlag(kCpuHasNEON) && width >= 16) { |
|
229 I422ToYUY2Row = I422ToYUY2Row_Any_NEON; |
|
230 if (IS_ALIGNED(width, 16)) { |
|
231 I422ToYUY2Row = I422ToYUY2Row_NEON; |
|
232 } |
|
233 } |
|
234 #endif |
|
235 |
|
236 for (int y = 0; y < height - 1; y += 2) { |
|
237 I422ToYUY2Row(src_y, src_u, src_v, dst_yuy2, width); |
|
238 I422ToYUY2Row(src_y + src_stride_y, src_u, src_v, |
|
239 dst_yuy2 + dst_stride_yuy2, width); |
|
240 src_y += src_stride_y * 2; |
|
241 src_u += src_stride_u; |
|
242 src_v += src_stride_v; |
|
243 dst_yuy2 += dst_stride_yuy2 * 2; |
|
244 } |
|
245 if (height & 1) { |
|
246 I422ToYUY2Row(src_y, src_u, src_v, dst_yuy2, width); |
|
247 } |
|
248 return 0; |
|
249 } |
|
250 |
|
251 LIBYUV_API |
|
252 int I422ToUYVY(const uint8* src_y, int src_stride_y, |
|
253 const uint8* src_u, int src_stride_u, |
|
254 const uint8* src_v, int src_stride_v, |
|
255 uint8* dst_uyvy, int dst_stride_uyvy, |
|
256 int width, int height) { |
|
257 if (!src_y || !src_u || !src_v || !dst_uyvy || |
|
258 width <= 0 || height == 0) { |
|
259 return -1; |
|
260 } |
|
261 // Negative height means invert the image. |
|
262 if (height < 0) { |
|
263 height = -height; |
|
264 dst_uyvy = dst_uyvy + (height - 1) * dst_stride_uyvy; |
|
265 dst_stride_uyvy = -dst_stride_uyvy; |
|
266 } |
|
267 // Coalesce rows. |
|
268 if (src_stride_y == width && |
|
269 src_stride_u * 2 == width && |
|
270 src_stride_v * 2 == width && |
|
271 dst_stride_uyvy == width * 2) { |
|
272 width *= height; |
|
273 height = 1; |
|
274 src_stride_y = src_stride_u = src_stride_v = dst_stride_uyvy = 0; |
|
275 } |
|
276 void (*I422ToUYVYRow)(const uint8* src_y, const uint8* src_u, |
|
277 const uint8* src_v, uint8* dst_uyvy, int width) = |
|
278 I422ToUYVYRow_C; |
|
279 #if defined(HAS_I422TOUYVYROW_SSE2) |
|
280 if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { |
|
281 I422ToUYVYRow = I422ToUYVYRow_Any_SSE2; |
|
282 if (IS_ALIGNED(width, 16)) { |
|
283 I422ToUYVYRow = I422ToUYVYRow_SSE2; |
|
284 } |
|
285 } |
|
286 #elif defined(HAS_I422TOUYVYROW_NEON) |
|
287 if (TestCpuFlag(kCpuHasNEON) && width >= 16) { |
|
288 I422ToUYVYRow = I422ToUYVYRow_Any_NEON; |
|
289 if (IS_ALIGNED(width, 16)) { |
|
290 I422ToUYVYRow = I422ToUYVYRow_NEON; |
|
291 } |
|
292 } |
|
293 #endif |
|
294 |
|
295 for (int y = 0; y < height; ++y) { |
|
296 I422ToUYVYRow(src_y, src_u, src_v, dst_uyvy, width); |
|
297 src_y += src_stride_y; |
|
298 src_u += src_stride_u; |
|
299 src_v += src_stride_v; |
|
300 dst_uyvy += dst_stride_uyvy; |
|
301 } |
|
302 return 0; |
|
303 } |
|
304 |
|
305 LIBYUV_API |
|
306 int I420ToUYVY(const uint8* src_y, int src_stride_y, |
|
307 const uint8* src_u, int src_stride_u, |
|
308 const uint8* src_v, int src_stride_v, |
|
309 uint8* dst_uyvy, int dst_stride_uyvy, |
|
310 int width, int height) { |
|
311 if (!src_y || !src_u || !src_v || !dst_uyvy || |
|
312 width <= 0 || height == 0) { |
|
313 return -1; |
|
314 } |
|
315 // Negative height means invert the image. |
|
316 if (height < 0) { |
|
317 height = -height; |
|
318 dst_uyvy = dst_uyvy + (height - 1) * dst_stride_uyvy; |
|
319 dst_stride_uyvy = -dst_stride_uyvy; |
|
320 } |
|
321 void (*I422ToUYVYRow)(const uint8* src_y, const uint8* src_u, |
|
322 const uint8* src_v, uint8* dst_uyvy, int width) = |
|
323 I422ToUYVYRow_C; |
|
324 #if defined(HAS_I422TOUYVYROW_SSE2) |
|
325 if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { |
|
326 I422ToUYVYRow = I422ToUYVYRow_Any_SSE2; |
|
327 if (IS_ALIGNED(width, 16)) { |
|
328 I422ToUYVYRow = I422ToUYVYRow_SSE2; |
|
329 } |
|
330 } |
|
331 #elif defined(HAS_I422TOUYVYROW_NEON) |
|
332 if (TestCpuFlag(kCpuHasNEON) && width >= 16) { |
|
333 I422ToUYVYRow = I422ToUYVYRow_Any_NEON; |
|
334 if (IS_ALIGNED(width, 16)) { |
|
335 I422ToUYVYRow = I422ToUYVYRow_NEON; |
|
336 } |
|
337 } |
|
338 #endif |
|
339 |
|
340 for (int y = 0; y < height - 1; y += 2) { |
|
341 I422ToUYVYRow(src_y, src_u, src_v, dst_uyvy, width); |
|
342 I422ToUYVYRow(src_y + src_stride_y, src_u, src_v, |
|
343 dst_uyvy + dst_stride_uyvy, width); |
|
344 src_y += src_stride_y * 2; |
|
345 src_u += src_stride_u; |
|
346 src_v += src_stride_v; |
|
347 dst_uyvy += dst_stride_uyvy * 2; |
|
348 } |
|
349 if (height & 1) { |
|
350 I422ToUYVYRow(src_y, src_u, src_v, dst_uyvy, width); |
|
351 } |
|
352 return 0; |
|
353 } |
|
354 |
|
355 LIBYUV_API |
|
356 int I420ToNV12(const uint8* src_y, int src_stride_y, |
|
357 const uint8* src_u, int src_stride_u, |
|
358 const uint8* src_v, int src_stride_v, |
|
359 uint8* dst_y, int dst_stride_y, |
|
360 uint8* dst_uv, int dst_stride_uv, |
|
361 int width, int height) { |
|
362 if (!src_y || !src_u || !src_v || !dst_y || !dst_uv || |
|
363 width <= 0 || height == 0) { |
|
364 return -1; |
|
365 } |
|
366 // Negative height means invert the image. |
|
367 if (height < 0) { |
|
368 height = -height; |
|
369 int halfheight = (height + 1) >> 1; |
|
370 dst_y = dst_y + (height - 1) * dst_stride_y; |
|
371 dst_uv = dst_uv + (halfheight - 1) * dst_stride_uv; |
|
372 dst_stride_y = -dst_stride_y; |
|
373 dst_stride_uv = -dst_stride_uv; |
|
374 } |
|
375 // Coalesce rows. |
|
376 int halfwidth = (width + 1) >> 1; |
|
377 int halfheight = (height + 1) >> 1; |
|
378 if (src_stride_y == width && |
|
379 dst_stride_y == width) { |
|
380 width *= height; |
|
381 height = 1; |
|
382 src_stride_y = dst_stride_y = 0; |
|
383 } |
|
384 // Coalesce rows. |
|
385 if (src_stride_u == halfwidth && |
|
386 src_stride_v == halfwidth && |
|
387 dst_stride_uv == halfwidth * 2) { |
|
388 halfwidth *= halfheight; |
|
389 halfheight = 1; |
|
390 src_stride_u = src_stride_v = dst_stride_uv = 0; |
|
391 } |
|
392 void (*MergeUVRow_)(const uint8* src_u, const uint8* src_v, uint8* dst_uv, |
|
393 int width) = MergeUVRow_C; |
|
394 #if defined(HAS_MERGEUVROW_SSE2) |
|
395 if (TestCpuFlag(kCpuHasSSE2) && halfwidth >= 16) { |
|
396 MergeUVRow_ = MergeUVRow_Any_SSE2; |
|
397 if (IS_ALIGNED(halfwidth, 16)) { |
|
398 MergeUVRow_ = MergeUVRow_Unaligned_SSE2; |
|
399 if (IS_ALIGNED(src_u, 16) && IS_ALIGNED(src_stride_u, 16) && |
|
400 IS_ALIGNED(src_v, 16) && IS_ALIGNED(src_stride_v, 16) && |
|
401 IS_ALIGNED(dst_uv, 16) && IS_ALIGNED(dst_stride_uv, 16)) { |
|
402 MergeUVRow_ = MergeUVRow_SSE2; |
|
403 } |
|
404 } |
|
405 } |
|
406 #endif |
|
407 #if defined(HAS_MERGEUVROW_AVX2) |
|
408 if (TestCpuFlag(kCpuHasAVX2) && halfwidth >= 32) { |
|
409 MergeUVRow_ = MergeUVRow_Any_AVX2; |
|
410 if (IS_ALIGNED(halfwidth, 32)) { |
|
411 MergeUVRow_ = MergeUVRow_AVX2; |
|
412 } |
|
413 } |
|
414 #endif |
|
415 #if defined(HAS_MERGEUVROW_NEON) |
|
416 if (TestCpuFlag(kCpuHasNEON) && halfwidth >= 16) { |
|
417 MergeUVRow_ = MergeUVRow_Any_NEON; |
|
418 if (IS_ALIGNED(halfwidth, 16)) { |
|
419 MergeUVRow_ = MergeUVRow_NEON; |
|
420 } |
|
421 } |
|
422 #endif |
|
423 |
|
424 CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); |
|
425 for (int y = 0; y < halfheight; ++y) { |
|
426 // Merge a row of U and V into a row of UV. |
|
427 MergeUVRow_(src_u, src_v, dst_uv, halfwidth); |
|
428 src_u += src_stride_u; |
|
429 src_v += src_stride_v; |
|
430 dst_uv += dst_stride_uv; |
|
431 } |
|
432 return 0; |
|
433 } |
|
434 |
|
435 LIBYUV_API |
|
436 int I420ToNV21(const uint8* src_y, int src_stride_y, |
|
437 const uint8* src_u, int src_stride_u, |
|
438 const uint8* src_v, int src_stride_v, |
|
439 uint8* dst_y, int dst_stride_y, |
|
440 uint8* dst_vu, int dst_stride_vu, |
|
441 int width, int height) { |
|
442 return I420ToNV12(src_y, src_stride_y, |
|
443 src_v, src_stride_v, |
|
444 src_u, src_stride_u, |
|
445 dst_y, src_stride_y, |
|
446 dst_vu, dst_stride_vu, |
|
447 width, height); |
|
448 } |
|
449 |
|
450 // Convert I420 to ARGB. |
|
451 LIBYUV_API |
|
452 int I420ToARGB(const uint8* src_y, int src_stride_y, |
|
453 const uint8* src_u, int src_stride_u, |
|
454 const uint8* src_v, int src_stride_v, |
|
455 uint8* dst_argb, int dst_stride_argb, |
|
456 int width, int height) { |
|
457 if (!src_y || !src_u || !src_v || !dst_argb || |
|
458 width <= 0 || height == 0) { |
|
459 return -1; |
|
460 } |
|
461 // Negative height means invert the image. |
|
462 if (height < 0) { |
|
463 height = -height; |
|
464 dst_argb = dst_argb + (height - 1) * dst_stride_argb; |
|
465 dst_stride_argb = -dst_stride_argb; |
|
466 } |
|
467 void (*I422ToARGBRow)(const uint8* y_buf, |
|
468 const uint8* u_buf, |
|
469 const uint8* v_buf, |
|
470 uint8* rgb_buf, |
|
471 int width) = I422ToARGBRow_C; |
|
472 #if defined(HAS_I422TOARGBROW_SSSE3) |
|
473 if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { |
|
474 I422ToARGBRow = I422ToARGBRow_Any_SSSE3; |
|
475 if (IS_ALIGNED(width, 8)) { |
|
476 I422ToARGBRow = I422ToARGBRow_Unaligned_SSSE3; |
|
477 if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { |
|
478 I422ToARGBRow = I422ToARGBRow_SSSE3; |
|
479 } |
|
480 } |
|
481 } |
|
482 #endif |
|
483 #if defined(HAS_I422TOARGBROW_AVX2) |
|
484 if (TestCpuFlag(kCpuHasAVX2) && width >= 16) { |
|
485 I422ToARGBRow = I422ToARGBRow_Any_AVX2; |
|
486 if (IS_ALIGNED(width, 16)) { |
|
487 I422ToARGBRow = I422ToARGBRow_AVX2; |
|
488 } |
|
489 } |
|
490 #endif |
|
491 #if defined(HAS_I422TOARGBROW_NEON) |
|
492 if (TestCpuFlag(kCpuHasNEON) && width >= 8) { |
|
493 I422ToARGBRow = I422ToARGBRow_Any_NEON; |
|
494 if (IS_ALIGNED(width, 8)) { |
|
495 I422ToARGBRow = I422ToARGBRow_NEON; |
|
496 } |
|
497 } |
|
498 #endif |
|
499 #if defined(HAS_I422TOARGBROW_MIPS_DSPR2) |
|
500 if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) && |
|
501 IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) && |
|
502 IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) && |
|
503 IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) && |
|
504 IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) { |
|
505 I422ToARGBRow = I422ToARGBRow_MIPS_DSPR2; |
|
506 } |
|
507 #endif |
|
508 |
|
509 for (int y = 0; y < height; ++y) { |
|
510 I422ToARGBRow(src_y, src_u, src_v, dst_argb, width); |
|
511 dst_argb += dst_stride_argb; |
|
512 src_y += src_stride_y; |
|
513 if (y & 1) { |
|
514 src_u += src_stride_u; |
|
515 src_v += src_stride_v; |
|
516 } |
|
517 } |
|
518 return 0; |
|
519 } |
|
520 |
|
521 // Convert I420 to BGRA. |
|
522 LIBYUV_API |
|
523 int I420ToBGRA(const uint8* src_y, int src_stride_y, |
|
524 const uint8* src_u, int src_stride_u, |
|
525 const uint8* src_v, int src_stride_v, |
|
526 uint8* dst_bgra, int dst_stride_bgra, |
|
527 int width, int height) { |
|
528 if (!src_y || !src_u || !src_v || !dst_bgra || |
|
529 width <= 0 || height == 0) { |
|
530 return -1; |
|
531 } |
|
532 // Negative height means invert the image. |
|
533 if (height < 0) { |
|
534 height = -height; |
|
535 dst_bgra = dst_bgra + (height - 1) * dst_stride_bgra; |
|
536 dst_stride_bgra = -dst_stride_bgra; |
|
537 } |
|
538 void (*I422ToBGRARow)(const uint8* y_buf, |
|
539 const uint8* u_buf, |
|
540 const uint8* v_buf, |
|
541 uint8* rgb_buf, |
|
542 int width) = I422ToBGRARow_C; |
|
543 #if defined(HAS_I422TOBGRAROW_SSSE3) |
|
544 if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { |
|
545 I422ToBGRARow = I422ToBGRARow_Any_SSSE3; |
|
546 if (IS_ALIGNED(width, 8)) { |
|
547 I422ToBGRARow = I422ToBGRARow_Unaligned_SSSE3; |
|
548 if (IS_ALIGNED(dst_bgra, 16) && IS_ALIGNED(dst_stride_bgra, 16)) { |
|
549 I422ToBGRARow = I422ToBGRARow_SSSE3; |
|
550 } |
|
551 } |
|
552 } |
|
553 #elif defined(HAS_I422TOBGRAROW_NEON) |
|
554 if (TestCpuFlag(kCpuHasNEON) && width >= 8) { |
|
555 I422ToBGRARow = I422ToBGRARow_Any_NEON; |
|
556 if (IS_ALIGNED(width, 8)) { |
|
557 I422ToBGRARow = I422ToBGRARow_NEON; |
|
558 } |
|
559 } |
|
560 #elif defined(HAS_I422TOBGRAROW_MIPS_DSPR2) |
|
561 if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) && |
|
562 IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) && |
|
563 IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) && |
|
564 IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) && |
|
565 IS_ALIGNED(dst_bgra, 4) && IS_ALIGNED(dst_stride_bgra, 4)) { |
|
566 I422ToBGRARow = I422ToBGRARow_MIPS_DSPR2; |
|
567 } |
|
568 #endif |
|
569 |
|
570 for (int y = 0; y < height; ++y) { |
|
571 I422ToBGRARow(src_y, src_u, src_v, dst_bgra, width); |
|
572 dst_bgra += dst_stride_bgra; |
|
573 src_y += src_stride_y; |
|
574 if (y & 1) { |
|
575 src_u += src_stride_u; |
|
576 src_v += src_stride_v; |
|
577 } |
|
578 } |
|
579 return 0; |
|
580 } |
|
581 |
|
582 // Convert I420 to ABGR. |
|
583 LIBYUV_API |
|
584 int I420ToABGR(const uint8* src_y, int src_stride_y, |
|
585 const uint8* src_u, int src_stride_u, |
|
586 const uint8* src_v, int src_stride_v, |
|
587 uint8* dst_abgr, int dst_stride_abgr, |
|
588 int width, int height) { |
|
589 if (!src_y || !src_u || !src_v || !dst_abgr || |
|
590 width <= 0 || height == 0) { |
|
591 return -1; |
|
592 } |
|
593 // Negative height means invert the image. |
|
594 if (height < 0) { |
|
595 height = -height; |
|
596 dst_abgr = dst_abgr + (height - 1) * dst_stride_abgr; |
|
597 dst_stride_abgr = -dst_stride_abgr; |
|
598 } |
|
599 void (*I422ToABGRRow)(const uint8* y_buf, |
|
600 const uint8* u_buf, |
|
601 const uint8* v_buf, |
|
602 uint8* rgb_buf, |
|
603 int width) = I422ToABGRRow_C; |
|
604 #if defined(HAS_I422TOABGRROW_SSSE3) |
|
605 if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { |
|
606 I422ToABGRRow = I422ToABGRRow_Any_SSSE3; |
|
607 if (IS_ALIGNED(width, 8)) { |
|
608 I422ToABGRRow = I422ToABGRRow_Unaligned_SSSE3; |
|
609 if (IS_ALIGNED(dst_abgr, 16) && IS_ALIGNED(dst_stride_abgr, 16)) { |
|
610 I422ToABGRRow = I422ToABGRRow_SSSE3; |
|
611 } |
|
612 } |
|
613 } |
|
614 #elif defined(HAS_I422TOABGRROW_NEON) |
|
615 if (TestCpuFlag(kCpuHasNEON) && width >= 8) { |
|
616 I422ToABGRRow = I422ToABGRRow_Any_NEON; |
|
617 if (IS_ALIGNED(width, 8)) { |
|
618 I422ToABGRRow = I422ToABGRRow_NEON; |
|
619 } |
|
620 } |
|
621 #endif |
|
622 |
|
623 for (int y = 0; y < height; ++y) { |
|
624 I422ToABGRRow(src_y, src_u, src_v, dst_abgr, width); |
|
625 dst_abgr += dst_stride_abgr; |
|
626 src_y += src_stride_y; |
|
627 if (y & 1) { |
|
628 src_u += src_stride_u; |
|
629 src_v += src_stride_v; |
|
630 } |
|
631 } |
|
632 return 0; |
|
633 } |
|
634 |
|
635 // Convert I420 to RGBA. |
|
636 LIBYUV_API |
|
637 int I420ToRGBA(const uint8* src_y, int src_stride_y, |
|
638 const uint8* src_u, int src_stride_u, |
|
639 const uint8* src_v, int src_stride_v, |
|
640 uint8* dst_rgba, int dst_stride_rgba, |
|
641 int width, int height) { |
|
642 if (!src_y || !src_u || !src_v || !dst_rgba || |
|
643 width <= 0 || height == 0) { |
|
644 return -1; |
|
645 } |
|
646 // Negative height means invert the image. |
|
647 if (height < 0) { |
|
648 height = -height; |
|
649 dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba; |
|
650 dst_stride_rgba = -dst_stride_rgba; |
|
651 } |
|
652 void (*I422ToRGBARow)(const uint8* y_buf, |
|
653 const uint8* u_buf, |
|
654 const uint8* v_buf, |
|
655 uint8* rgb_buf, |
|
656 int width) = I422ToRGBARow_C; |
|
657 #if defined(HAS_I422TORGBAROW_SSSE3) |
|
658 if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { |
|
659 I422ToRGBARow = I422ToRGBARow_Any_SSSE3; |
|
660 if (IS_ALIGNED(width, 8)) { |
|
661 I422ToRGBARow = I422ToRGBARow_Unaligned_SSSE3; |
|
662 if (IS_ALIGNED(dst_rgba, 16) && IS_ALIGNED(dst_stride_rgba, 16)) { |
|
663 I422ToRGBARow = I422ToRGBARow_SSSE3; |
|
664 } |
|
665 } |
|
666 } |
|
667 #elif defined(HAS_I422TORGBAROW_NEON) |
|
668 if (TestCpuFlag(kCpuHasNEON) && width >= 8) { |
|
669 I422ToRGBARow = I422ToRGBARow_Any_NEON; |
|
670 if (IS_ALIGNED(width, 8)) { |
|
671 I422ToRGBARow = I422ToRGBARow_NEON; |
|
672 } |
|
673 } |
|
674 #endif |
|
675 |
|
676 for (int y = 0; y < height; ++y) { |
|
677 I422ToRGBARow(src_y, src_u, src_v, dst_rgba, width); |
|
678 dst_rgba += dst_stride_rgba; |
|
679 src_y += src_stride_y; |
|
680 if (y & 1) { |
|
681 src_u += src_stride_u; |
|
682 src_v += src_stride_v; |
|
683 } |
|
684 } |
|
685 return 0; |
|
686 } |
|
687 |
|
688 // Convert I420 to RGB24. |
|
689 LIBYUV_API |
|
690 int I420ToRGB24(const uint8* src_y, int src_stride_y, |
|
691 const uint8* src_u, int src_stride_u, |
|
692 const uint8* src_v, int src_stride_v, |
|
693 uint8* dst_rgb24, int dst_stride_rgb24, |
|
694 int width, int height) { |
|
695 if (!src_y || !src_u || !src_v || !dst_rgb24 || |
|
696 width <= 0 || height == 0) { |
|
697 return -1; |
|
698 } |
|
699 // Negative height means invert the image. |
|
700 if (height < 0) { |
|
701 height = -height; |
|
702 dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24; |
|
703 dst_stride_rgb24 = -dst_stride_rgb24; |
|
704 } |
|
705 void (*I422ToRGB24Row)(const uint8* y_buf, |
|
706 const uint8* u_buf, |
|
707 const uint8* v_buf, |
|
708 uint8* rgb_buf, |
|
709 int width) = I422ToRGB24Row_C; |
|
710 #if defined(HAS_I422TORGB24ROW_SSSE3) |
|
711 if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { |
|
712 I422ToRGB24Row = I422ToRGB24Row_Any_SSSE3; |
|
713 if (IS_ALIGNED(width, 8)) { |
|
714 I422ToRGB24Row = I422ToRGB24Row_SSSE3; |
|
715 } |
|
716 } |
|
717 #elif defined(HAS_I422TORGB24ROW_NEON) |
|
718 if (TestCpuFlag(kCpuHasNEON) && width >= 8) { |
|
719 I422ToRGB24Row = I422ToRGB24Row_Any_NEON; |
|
720 if (IS_ALIGNED(width, 8)) { |
|
721 I422ToRGB24Row = I422ToRGB24Row_NEON; |
|
722 } |
|
723 } |
|
724 #endif |
|
725 |
|
726 for (int y = 0; y < height; ++y) { |
|
727 I422ToRGB24Row(src_y, src_u, src_v, dst_rgb24, width); |
|
728 dst_rgb24 += dst_stride_rgb24; |
|
729 src_y += src_stride_y; |
|
730 if (y & 1) { |
|
731 src_u += src_stride_u; |
|
732 src_v += src_stride_v; |
|
733 } |
|
734 } |
|
735 return 0; |
|
736 } |
|
737 |
|
738 // Convert I420 to RAW. |
|
739 LIBYUV_API |
|
740 int I420ToRAW(const uint8* src_y, int src_stride_y, |
|
741 const uint8* src_u, int src_stride_u, |
|
742 const uint8* src_v, int src_stride_v, |
|
743 uint8* dst_raw, int dst_stride_raw, |
|
744 int width, int height) { |
|
745 if (!src_y || !src_u || !src_v || !dst_raw || |
|
746 width <= 0 || height == 0) { |
|
747 return -1; |
|
748 } |
|
749 // Negative height means invert the image. |
|
750 if (height < 0) { |
|
751 height = -height; |
|
752 dst_raw = dst_raw + (height - 1) * dst_stride_raw; |
|
753 dst_stride_raw = -dst_stride_raw; |
|
754 } |
|
755 void (*I422ToRAWRow)(const uint8* y_buf, |
|
756 const uint8* u_buf, |
|
757 const uint8* v_buf, |
|
758 uint8* rgb_buf, |
|
759 int width) = I422ToRAWRow_C; |
|
760 #if defined(HAS_I422TORAWROW_SSSE3) |
|
761 if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { |
|
762 I422ToRAWRow = I422ToRAWRow_Any_SSSE3; |
|
763 if (IS_ALIGNED(width, 8)) { |
|
764 I422ToRAWRow = I422ToRAWRow_SSSE3; |
|
765 } |
|
766 } |
|
767 #elif defined(HAS_I422TORAWROW_NEON) |
|
768 if (TestCpuFlag(kCpuHasNEON) && width >= 8) { |
|
769 I422ToRAWRow = I422ToRAWRow_Any_NEON; |
|
770 if (IS_ALIGNED(width, 8)) { |
|
771 I422ToRAWRow = I422ToRAWRow_NEON; |
|
772 } |
|
773 } |
|
774 #endif |
|
775 |
|
776 for (int y = 0; y < height; ++y) { |
|
777 I422ToRAWRow(src_y, src_u, src_v, dst_raw, width); |
|
778 dst_raw += dst_stride_raw; |
|
779 src_y += src_stride_y; |
|
780 if (y & 1) { |
|
781 src_u += src_stride_u; |
|
782 src_v += src_stride_v; |
|
783 } |
|
784 } |
|
785 return 0; |
|
786 } |
|
787 |
|
788 // Convert I420 to ARGB1555. |
|
789 LIBYUV_API |
|
790 int I420ToARGB1555(const uint8* src_y, int src_stride_y, |
|
791 const uint8* src_u, int src_stride_u, |
|
792 const uint8* src_v, int src_stride_v, |
|
793 uint8* dst_argb1555, int dst_stride_argb1555, |
|
794 int width, int height) { |
|
795 if (!src_y || !src_u || !src_v || !dst_argb1555 || |
|
796 width <= 0 || height == 0) { |
|
797 return -1; |
|
798 } |
|
799 // Negative height means invert the image. |
|
800 if (height < 0) { |
|
801 height = -height; |
|
802 dst_argb1555 = dst_argb1555 + (height - 1) * dst_stride_argb1555; |
|
803 dst_stride_argb1555 = -dst_stride_argb1555; |
|
804 } |
|
805 void (*I422ToARGB1555Row)(const uint8* y_buf, |
|
806 const uint8* u_buf, |
|
807 const uint8* v_buf, |
|
808 uint8* rgb_buf, |
|
809 int width) = I422ToARGB1555Row_C; |
|
810 #if defined(HAS_I422TOARGB1555ROW_SSSE3) |
|
811 if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { |
|
812 I422ToARGB1555Row = I422ToARGB1555Row_Any_SSSE3; |
|
813 if (IS_ALIGNED(width, 8)) { |
|
814 I422ToARGB1555Row = I422ToARGB1555Row_SSSE3; |
|
815 } |
|
816 } |
|
817 #elif defined(HAS_I422TOARGB1555ROW_NEON) |
|
818 if (TestCpuFlag(kCpuHasNEON) && width >= 8) { |
|
819 I422ToARGB1555Row = I422ToARGB1555Row_Any_NEON; |
|
820 if (IS_ALIGNED(width, 8)) { |
|
821 I422ToARGB1555Row = I422ToARGB1555Row_NEON; |
|
822 } |
|
823 } |
|
824 #endif |
|
825 |
|
826 for (int y = 0; y < height; ++y) { |
|
827 I422ToARGB1555Row(src_y, src_u, src_v, dst_argb1555, width); |
|
828 dst_argb1555 += dst_stride_argb1555; |
|
829 src_y += src_stride_y; |
|
830 if (y & 1) { |
|
831 src_u += src_stride_u; |
|
832 src_v += src_stride_v; |
|
833 } |
|
834 } |
|
835 return 0; |
|
836 } |
|
837 |
|
838 |
|
839 // Convert I420 to ARGB4444. |
|
840 LIBYUV_API |
|
841 int I420ToARGB4444(const uint8* src_y, int src_stride_y, |
|
842 const uint8* src_u, int src_stride_u, |
|
843 const uint8* src_v, int src_stride_v, |
|
844 uint8* dst_argb4444, int dst_stride_argb4444, |
|
845 int width, int height) { |
|
846 if (!src_y || !src_u || !src_v || !dst_argb4444 || |
|
847 width <= 0 || height == 0) { |
|
848 return -1; |
|
849 } |
|
850 // Negative height means invert the image. |
|
851 if (height < 0) { |
|
852 height = -height; |
|
853 dst_argb4444 = dst_argb4444 + (height - 1) * dst_stride_argb4444; |
|
854 dst_stride_argb4444 = -dst_stride_argb4444; |
|
855 } |
|
856 void (*I422ToARGB4444Row)(const uint8* y_buf, |
|
857 const uint8* u_buf, |
|
858 const uint8* v_buf, |
|
859 uint8* rgb_buf, |
|
860 int width) = I422ToARGB4444Row_C; |
|
861 #if defined(HAS_I422TOARGB4444ROW_SSSE3) |
|
862 if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { |
|
863 I422ToARGB4444Row = I422ToARGB4444Row_Any_SSSE3; |
|
864 if (IS_ALIGNED(width, 8)) { |
|
865 I422ToARGB4444Row = I422ToARGB4444Row_SSSE3; |
|
866 } |
|
867 } |
|
868 #elif defined(HAS_I422TOARGB4444ROW_NEON) |
|
869 if (TestCpuFlag(kCpuHasNEON) && width >= 8) { |
|
870 I422ToARGB4444Row = I422ToARGB4444Row_Any_NEON; |
|
871 if (IS_ALIGNED(width, 8)) { |
|
872 I422ToARGB4444Row = I422ToARGB4444Row_NEON; |
|
873 } |
|
874 } |
|
875 #endif |
|
876 |
|
877 for (int y = 0; y < height; ++y) { |
|
878 I422ToARGB4444Row(src_y, src_u, src_v, dst_argb4444, width); |
|
879 dst_argb4444 += dst_stride_argb4444; |
|
880 src_y += src_stride_y; |
|
881 if (y & 1) { |
|
882 src_u += src_stride_u; |
|
883 src_v += src_stride_v; |
|
884 } |
|
885 } |
|
886 return 0; |
|
887 } |
|
888 |
|
889 // Convert I420 to RGB565. |
|
890 LIBYUV_API |
|
891 int I420ToRGB565(const uint8* src_y, int src_stride_y, |
|
892 const uint8* src_u, int src_stride_u, |
|
893 const uint8* src_v, int src_stride_v, |
|
894 uint8* dst_rgb565, int dst_stride_rgb565, |
|
895 int width, int height) { |
|
896 if (!src_y || !src_u || !src_v || !dst_rgb565 || |
|
897 width <= 0 || height == 0) { |
|
898 return -1; |
|
899 } |
|
900 // Negative height means invert the image. |
|
901 if (height < 0) { |
|
902 height = -height; |
|
903 dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565; |
|
904 dst_stride_rgb565 = -dst_stride_rgb565; |
|
905 } |
|
906 void (*I422ToRGB565Row)(const uint8* y_buf, |
|
907 const uint8* u_buf, |
|
908 const uint8* v_buf, |
|
909 uint8* rgb_buf, |
|
910 int width) = I422ToRGB565Row_C; |
|
911 #if defined(HAS_I422TORGB565ROW_SSSE3) |
|
912 if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { |
|
913 I422ToRGB565Row = I422ToRGB565Row_Any_SSSE3; |
|
914 if (IS_ALIGNED(width, 8)) { |
|
915 I422ToRGB565Row = I422ToRGB565Row_SSSE3; |
|
916 } |
|
917 } |
|
918 #elif defined(HAS_I422TORGB565ROW_NEON) |
|
919 if (TestCpuFlag(kCpuHasNEON) && width >= 8) { |
|
920 I422ToRGB565Row = I422ToRGB565Row_Any_NEON; |
|
921 if (IS_ALIGNED(width, 8)) { |
|
922 I422ToRGB565Row = I422ToRGB565Row_NEON; |
|
923 } |
|
924 } |
|
925 #endif |
|
926 |
|
927 for (int y = 0; y < height; ++y) { |
|
928 I422ToRGB565Row(src_y, src_u, src_v, dst_rgb565, width); |
|
929 dst_rgb565 += dst_stride_rgb565; |
|
930 src_y += src_stride_y; |
|
931 if (y & 1) { |
|
932 src_u += src_stride_u; |
|
933 src_v += src_stride_v; |
|
934 } |
|
935 } |
|
936 return 0; |
|
937 } |
|
938 |
|
939 // Convert I420 to specified format |
|
940 LIBYUV_API |
|
941 int ConvertFromI420(const uint8* y, int y_stride, |
|
942 const uint8* u, int u_stride, |
|
943 const uint8* v, int v_stride, |
|
944 uint8* dst_sample, int dst_sample_stride, |
|
945 int width, int height, |
|
946 uint32 fourcc) { |
|
947 uint32 format = CanonicalFourCC(fourcc); |
|
948 if (!y || !u|| !v || !dst_sample || |
|
949 width <= 0 || height == 0) { |
|
950 return -1; |
|
951 } |
|
952 int r = 0; |
|
953 switch (format) { |
|
954 // Single plane formats |
|
955 case FOURCC_YUY2: |
|
956 r = I420ToYUY2(y, y_stride, |
|
957 u, u_stride, |
|
958 v, v_stride, |
|
959 dst_sample, |
|
960 dst_sample_stride ? dst_sample_stride : width * 2, |
|
961 width, height); |
|
962 break; |
|
963 case FOURCC_UYVY: |
|
964 r = I420ToUYVY(y, y_stride, |
|
965 u, u_stride, |
|
966 v, v_stride, |
|
967 dst_sample, |
|
968 dst_sample_stride ? dst_sample_stride : width * 2, |
|
969 width, height); |
|
970 break; |
|
971 case FOURCC_RGBP: |
|
972 r = I420ToRGB565(y, y_stride, |
|
973 u, u_stride, |
|
974 v, v_stride, |
|
975 dst_sample, |
|
976 dst_sample_stride ? dst_sample_stride : width * 2, |
|
977 width, height); |
|
978 break; |
|
979 case FOURCC_RGBO: |
|
980 r = I420ToARGB1555(y, y_stride, |
|
981 u, u_stride, |
|
982 v, v_stride, |
|
983 dst_sample, |
|
984 dst_sample_stride ? dst_sample_stride : width * 2, |
|
985 width, height); |
|
986 break; |
|
987 case FOURCC_R444: |
|
988 r = I420ToARGB4444(y, y_stride, |
|
989 u, u_stride, |
|
990 v, v_stride, |
|
991 dst_sample, |
|
992 dst_sample_stride ? dst_sample_stride : width * 2, |
|
993 width, height); |
|
994 break; |
|
995 case FOURCC_24BG: |
|
996 r = I420ToRGB24(y, y_stride, |
|
997 u, u_stride, |
|
998 v, v_stride, |
|
999 dst_sample, |
|
1000 dst_sample_stride ? dst_sample_stride : width * 3, |
|
1001 width, height); |
|
1002 break; |
|
1003 case FOURCC_RAW: |
|
1004 r = I420ToRAW(y, y_stride, |
|
1005 u, u_stride, |
|
1006 v, v_stride, |
|
1007 dst_sample, |
|
1008 dst_sample_stride ? dst_sample_stride : width * 3, |
|
1009 width, height); |
|
1010 break; |
|
1011 case FOURCC_ARGB: |
|
1012 r = I420ToARGB(y, y_stride, |
|
1013 u, u_stride, |
|
1014 v, v_stride, |
|
1015 dst_sample, |
|
1016 dst_sample_stride ? dst_sample_stride : width * 4, |
|
1017 width, height); |
|
1018 break; |
|
1019 case FOURCC_BGRA: |
|
1020 r = I420ToBGRA(y, y_stride, |
|
1021 u, u_stride, |
|
1022 v, v_stride, |
|
1023 dst_sample, |
|
1024 dst_sample_stride ? dst_sample_stride : width * 4, |
|
1025 width, height); |
|
1026 break; |
|
1027 case FOURCC_ABGR: |
|
1028 r = I420ToABGR(y, y_stride, |
|
1029 u, u_stride, |
|
1030 v, v_stride, |
|
1031 dst_sample, |
|
1032 dst_sample_stride ? dst_sample_stride : width * 4, |
|
1033 width, height); |
|
1034 break; |
|
1035 case FOURCC_RGBA: |
|
1036 r = I420ToRGBA(y, y_stride, |
|
1037 u, u_stride, |
|
1038 v, v_stride, |
|
1039 dst_sample, |
|
1040 dst_sample_stride ? dst_sample_stride : width * 4, |
|
1041 width, height); |
|
1042 break; |
|
1043 case FOURCC_BGGR: |
|
1044 r = I420ToBayerBGGR(y, y_stride, |
|
1045 u, u_stride, |
|
1046 v, v_stride, |
|
1047 dst_sample, |
|
1048 dst_sample_stride ? dst_sample_stride : width, |
|
1049 width, height); |
|
1050 break; |
|
1051 case FOURCC_GBRG: |
|
1052 r = I420ToBayerGBRG(y, y_stride, |
|
1053 u, u_stride, |
|
1054 v, v_stride, |
|
1055 dst_sample, |
|
1056 dst_sample_stride ? dst_sample_stride : width, |
|
1057 width, height); |
|
1058 break; |
|
1059 case FOURCC_GRBG: |
|
1060 r = I420ToBayerGRBG(y, y_stride, |
|
1061 u, u_stride, |
|
1062 v, v_stride, |
|
1063 dst_sample, |
|
1064 dst_sample_stride ? dst_sample_stride : width, |
|
1065 width, height); |
|
1066 break; |
|
1067 case FOURCC_RGGB: |
|
1068 r = I420ToBayerRGGB(y, y_stride, |
|
1069 u, u_stride, |
|
1070 v, v_stride, |
|
1071 dst_sample, |
|
1072 dst_sample_stride ? dst_sample_stride : width, |
|
1073 width, height); |
|
1074 break; |
|
1075 case FOURCC_I400: |
|
1076 r = I400Copy(y, y_stride, |
|
1077 dst_sample, |
|
1078 dst_sample_stride ? dst_sample_stride : width, |
|
1079 width, height); |
|
1080 break; |
|
1081 case FOURCC_NV12: { |
|
1082 uint8* dst_uv = dst_sample + width * height; |
|
1083 r = I420ToNV12(y, y_stride, |
|
1084 u, u_stride, |
|
1085 v, v_stride, |
|
1086 dst_sample, |
|
1087 dst_sample_stride ? dst_sample_stride : width, |
|
1088 dst_uv, |
|
1089 dst_sample_stride ? dst_sample_stride : width, |
|
1090 width, height); |
|
1091 break; |
|
1092 } |
|
1093 case FOURCC_NV21: { |
|
1094 uint8* dst_vu = dst_sample + width * height; |
|
1095 r = I420ToNV21(y, y_stride, |
|
1096 u, u_stride, |
|
1097 v, v_stride, |
|
1098 dst_sample, |
|
1099 dst_sample_stride ? dst_sample_stride : width, |
|
1100 dst_vu, |
|
1101 dst_sample_stride ? dst_sample_stride : width, |
|
1102 width, height); |
|
1103 break; |
|
1104 } |
|
1105 // TODO(fbarchard): Add M420 and Q420. |
|
1106 // Triplanar formats |
|
1107 // TODO(fbarchard): halfstride instead of halfwidth |
|
1108 case FOURCC_I420: |
|
1109 case FOURCC_YU12: |
|
1110 case FOURCC_YV12: { |
|
1111 int halfwidth = (width + 1) / 2; |
|
1112 int halfheight = (height + 1) / 2; |
|
1113 uint8* dst_u; |
|
1114 uint8* dst_v; |
|
1115 if (format == FOURCC_YV12) { |
|
1116 dst_v = dst_sample + width * height; |
|
1117 dst_u = dst_v + halfwidth * halfheight; |
|
1118 } else { |
|
1119 dst_u = dst_sample + width * height; |
|
1120 dst_v = dst_u + halfwidth * halfheight; |
|
1121 } |
|
1122 r = I420Copy(y, y_stride, |
|
1123 u, u_stride, |
|
1124 v, v_stride, |
|
1125 dst_sample, width, |
|
1126 dst_u, halfwidth, |
|
1127 dst_v, halfwidth, |
|
1128 width, height); |
|
1129 break; |
|
1130 } |
|
1131 case FOURCC_I422: |
|
1132 case FOURCC_YV16: { |
|
1133 int halfwidth = (width + 1) / 2; |
|
1134 uint8* dst_u; |
|
1135 uint8* dst_v; |
|
1136 if (format == FOURCC_YV16) { |
|
1137 dst_v = dst_sample + width * height; |
|
1138 dst_u = dst_v + halfwidth * height; |
|
1139 } else { |
|
1140 dst_u = dst_sample + width * height; |
|
1141 dst_v = dst_u + halfwidth * height; |
|
1142 } |
|
1143 r = I420ToI422(y, y_stride, |
|
1144 u, u_stride, |
|
1145 v, v_stride, |
|
1146 dst_sample, width, |
|
1147 dst_u, halfwidth, |
|
1148 dst_v, halfwidth, |
|
1149 width, height); |
|
1150 break; |
|
1151 } |
|
1152 case FOURCC_I444: |
|
1153 case FOURCC_YV24: { |
|
1154 uint8* dst_u; |
|
1155 uint8* dst_v; |
|
1156 if (format == FOURCC_YV24) { |
|
1157 dst_v = dst_sample + width * height; |
|
1158 dst_u = dst_v + width * height; |
|
1159 } else { |
|
1160 dst_u = dst_sample + width * height; |
|
1161 dst_v = dst_u + width * height; |
|
1162 } |
|
1163 r = I420ToI444(y, y_stride, |
|
1164 u, u_stride, |
|
1165 v, v_stride, |
|
1166 dst_sample, width, |
|
1167 dst_u, width, |
|
1168 dst_v, width, |
|
1169 width, height); |
|
1170 break; |
|
1171 } |
|
1172 case FOURCC_I411: { |
|
1173 int quarterwidth = (width + 3) / 4; |
|
1174 uint8* dst_u = dst_sample + width * height; |
|
1175 uint8* dst_v = dst_u + quarterwidth * height; |
|
1176 r = I420ToI411(y, y_stride, |
|
1177 u, u_stride, |
|
1178 v, v_stride, |
|
1179 dst_sample, width, |
|
1180 dst_u, quarterwidth, |
|
1181 dst_v, quarterwidth, |
|
1182 width, height); |
|
1183 break; |
|
1184 } |
|
1185 |
|
1186 // Formats not supported - MJPG, biplanar, some rgb formats. |
|
1187 default: |
|
1188 return -1; // unknown fourcc - return failure code. |
|
1189 } |
|
1190 return r; |
|
1191 } |
|
1192 |
|
1193 #ifdef __cplusplus |
|
1194 } // extern "C" |
|
1195 } // namespace libyuv |
|
1196 #endif |