1 /*
2 * Copyright 2011 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_argb.h"
12
13 #include "libyuv/cpu_id.h"
14 #ifdef HAVE_JPEG
15 #include "libyuv/mjpeg_decoder.h"
16 #endif
17 #include "libyuv/planar_functions.h" // For CopyPlane and ARGBShuffle.
18 #include "libyuv/rotate_argb.h"
19 #include "libyuv/row.h"
20 #include "libyuv/video_common.h"
21
22 #ifdef __cplusplus
23 namespace libyuv {
24 extern "C" {
25 #endif
26
27 // Copy ARGB with optional flipping
28 LIBYUV_API
ARGBCopy(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_argb,int dst_stride_argb,int width,int height)29 int ARGBCopy(const uint8_t* src_argb,
30 int src_stride_argb,
31 uint8_t* dst_argb,
32 int dst_stride_argb,
33 int width,
34 int height) {
35 if (!src_argb || !dst_argb || width <= 0 || height == 0) {
36 return -1;
37 }
38 // Negative height means invert the image.
39 if (height < 0) {
40 height = -height;
41 src_argb = src_argb + (height - 1) * src_stride_argb;
42 src_stride_argb = -src_stride_argb;
43 }
44
45 CopyPlane(src_argb, src_stride_argb, dst_argb, dst_stride_argb, width * 4,
46 height);
47 return 0;
48 }
49
50 // Convert I420 to ARGB with matrix
I420ToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)51 static int I420ToARGBMatrix(const uint8_t* src_y,
52 int src_stride_y,
53 const uint8_t* src_u,
54 int src_stride_u,
55 const uint8_t* src_v,
56 int src_stride_v,
57 uint8_t* dst_argb,
58 int dst_stride_argb,
59 const struct YuvConstants* yuvconstants,
60 int width,
61 int height) {
62 int y;
63 void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
64 const uint8_t* v_buf, uint8_t* rgb_buf,
65 const struct YuvConstants* yuvconstants, int width) =
66 I422ToARGBRow_C;
67 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
68 return -1;
69 }
70 // Negative height means invert the image.
71 if (height < 0) {
72 height = -height;
73 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
74 dst_stride_argb = -dst_stride_argb;
75 }
76 #if defined(HAS_I422TOARGBROW_SSSE3)
77 if (TestCpuFlag(kCpuHasSSSE3)) {
78 I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
79 if (IS_ALIGNED(width, 8)) {
80 I422ToARGBRow = I422ToARGBRow_SSSE3;
81 }
82 }
83 #endif
84 #if defined(HAS_I422TOARGBROW_AVX2)
85 if (TestCpuFlag(kCpuHasAVX2)) {
86 I422ToARGBRow = I422ToARGBRow_Any_AVX2;
87 if (IS_ALIGNED(width, 16)) {
88 I422ToARGBRow = I422ToARGBRow_AVX2;
89 }
90 }
91 #endif
92 #if defined(HAS_I422TOARGBROW_NEON)
93 if (TestCpuFlag(kCpuHasNEON)) {
94 I422ToARGBRow = I422ToARGBRow_Any_NEON;
95 if (IS_ALIGNED(width, 8)) {
96 I422ToARGBRow = I422ToARGBRow_NEON;
97 }
98 }
99 #endif
100 #if defined(HAS_I422TOARGBROW_MSA)
101 if (TestCpuFlag(kCpuHasMSA)) {
102 I422ToARGBRow = I422ToARGBRow_Any_MSA;
103 if (IS_ALIGNED(width, 8)) {
104 I422ToARGBRow = I422ToARGBRow_MSA;
105 }
106 }
107 #endif
108
109 for (y = 0; y < height; ++y) {
110 I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
111 dst_argb += dst_stride_argb;
112 src_y += src_stride_y;
113 if (y & 1) {
114 src_u += src_stride_u;
115 src_v += src_stride_v;
116 }
117 }
118 return 0;
119 }
120
121 // Convert I420 to ARGB.
122 LIBYUV_API
I420ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)123 int I420ToARGB(const uint8_t* src_y,
124 int src_stride_y,
125 const uint8_t* src_u,
126 int src_stride_u,
127 const uint8_t* src_v,
128 int src_stride_v,
129 uint8_t* dst_argb,
130 int dst_stride_argb,
131 int width,
132 int height) {
133 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
134 src_stride_v, dst_argb, dst_stride_argb,
135 &kYuvI601Constants, width, height);
136 }
137
138 // Convert I420 to ABGR.
139 LIBYUV_API
I420ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)140 int I420ToABGR(const uint8_t* src_y,
141 int src_stride_y,
142 const uint8_t* src_u,
143 int src_stride_u,
144 const uint8_t* src_v,
145 int src_stride_v,
146 uint8_t* dst_abgr,
147 int dst_stride_abgr,
148 int width,
149 int height) {
150 return I420ToARGBMatrix(src_y, src_stride_y, src_v,
151 src_stride_v, // Swap U and V
152 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
153 &kYvuI601Constants, // Use Yvu matrix
154 width, height);
155 }
156
157 // Convert J420 to ARGB.
158 LIBYUV_API
J420ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)159 int J420ToARGB(const uint8_t* src_y,
160 int src_stride_y,
161 const uint8_t* src_u,
162 int src_stride_u,
163 const uint8_t* src_v,
164 int src_stride_v,
165 uint8_t* dst_argb,
166 int dst_stride_argb,
167 int width,
168 int height) {
169 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
170 src_stride_v, dst_argb, dst_stride_argb,
171 &kYuvJPEGConstants, width, height);
172 }
173
174 // Convert J420 to ABGR.
175 LIBYUV_API
J420ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)176 int J420ToABGR(const uint8_t* src_y,
177 int src_stride_y,
178 const uint8_t* src_u,
179 int src_stride_u,
180 const uint8_t* src_v,
181 int src_stride_v,
182 uint8_t* dst_abgr,
183 int dst_stride_abgr,
184 int width,
185 int height) {
186 return I420ToARGBMatrix(src_y, src_stride_y, src_v,
187 src_stride_v, // Swap U and V
188 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
189 &kYvuJPEGConstants, // Use Yvu matrix
190 width, height);
191 }
192
193 // Convert H420 to ARGB.
194 LIBYUV_API
H420ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)195 int H420ToARGB(const uint8_t* src_y,
196 int src_stride_y,
197 const uint8_t* src_u,
198 int src_stride_u,
199 const uint8_t* src_v,
200 int src_stride_v,
201 uint8_t* dst_argb,
202 int dst_stride_argb,
203 int width,
204 int height) {
205 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
206 src_stride_v, dst_argb, dst_stride_argb,
207 &kYuvH709Constants, width, height);
208 }
209
210 // Convert H420 to ABGR.
211 LIBYUV_API
H420ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)212 int H420ToABGR(const uint8_t* src_y,
213 int src_stride_y,
214 const uint8_t* src_u,
215 int src_stride_u,
216 const uint8_t* src_v,
217 int src_stride_v,
218 uint8_t* dst_abgr,
219 int dst_stride_abgr,
220 int width,
221 int height) {
222 return I420ToARGBMatrix(src_y, src_stride_y, src_v,
223 src_stride_v, // Swap U and V
224 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
225 &kYvuH709Constants, // Use Yvu matrix
226 width, height);
227 }
228
229 // Convert I422 to ARGB with matrix
I422ToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)230 static int I422ToARGBMatrix(const uint8_t* src_y,
231 int src_stride_y,
232 const uint8_t* src_u,
233 int src_stride_u,
234 const uint8_t* src_v,
235 int src_stride_v,
236 uint8_t* dst_argb,
237 int dst_stride_argb,
238 const struct YuvConstants* yuvconstants,
239 int width,
240 int height) {
241 int y;
242 void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
243 const uint8_t* v_buf, uint8_t* rgb_buf,
244 const struct YuvConstants* yuvconstants, int width) =
245 I422ToARGBRow_C;
246 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
247 return -1;
248 }
249 // Negative height means invert the image.
250 if (height < 0) {
251 height = -height;
252 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
253 dst_stride_argb = -dst_stride_argb;
254 }
255 // Coalesce rows.
256 if (src_stride_y == width && src_stride_u * 2 == width &&
257 src_stride_v * 2 == width && dst_stride_argb == width * 4) {
258 width *= height;
259 height = 1;
260 src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
261 }
262 #if defined(HAS_I422TOARGBROW_SSSE3)
263 if (TestCpuFlag(kCpuHasSSSE3)) {
264 I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
265 if (IS_ALIGNED(width, 8)) {
266 I422ToARGBRow = I422ToARGBRow_SSSE3;
267 }
268 }
269 #endif
270 #if defined(HAS_I422TOARGBROW_AVX2)
271 if (TestCpuFlag(kCpuHasAVX2)) {
272 I422ToARGBRow = I422ToARGBRow_Any_AVX2;
273 if (IS_ALIGNED(width, 16)) {
274 I422ToARGBRow = I422ToARGBRow_AVX2;
275 }
276 }
277 #endif
278 #if defined(HAS_I422TOARGBROW_NEON)
279 if (TestCpuFlag(kCpuHasNEON)) {
280 I422ToARGBRow = I422ToARGBRow_Any_NEON;
281 if (IS_ALIGNED(width, 8)) {
282 I422ToARGBRow = I422ToARGBRow_NEON;
283 }
284 }
285 #endif
286 #if defined(HAS_I422TOARGBROW_MSA)
287 if (TestCpuFlag(kCpuHasMSA)) {
288 I422ToARGBRow = I422ToARGBRow_Any_MSA;
289 if (IS_ALIGNED(width, 8)) {
290 I422ToARGBRow = I422ToARGBRow_MSA;
291 }
292 }
293 #endif
294
295 for (y = 0; y < height; ++y) {
296 I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
297 dst_argb += dst_stride_argb;
298 src_y += src_stride_y;
299 src_u += src_stride_u;
300 src_v += src_stride_v;
301 }
302 return 0;
303 }
304
305 // Convert I422 to ARGB.
306 LIBYUV_API
I422ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)307 int I422ToARGB(const uint8_t* src_y,
308 int src_stride_y,
309 const uint8_t* src_u,
310 int src_stride_u,
311 const uint8_t* src_v,
312 int src_stride_v,
313 uint8_t* dst_argb,
314 int dst_stride_argb,
315 int width,
316 int height) {
317 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
318 src_stride_v, dst_argb, dst_stride_argb,
319 &kYuvI601Constants, width, height);
320 }
321
322 // Convert I422 to ABGR.
323 LIBYUV_API
I422ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)324 int I422ToABGR(const uint8_t* src_y,
325 int src_stride_y,
326 const uint8_t* src_u,
327 int src_stride_u,
328 const uint8_t* src_v,
329 int src_stride_v,
330 uint8_t* dst_abgr,
331 int dst_stride_abgr,
332 int width,
333 int height) {
334 return I422ToARGBMatrix(src_y, src_stride_y, src_v,
335 src_stride_v, // Swap U and V
336 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
337 &kYvuI601Constants, // Use Yvu matrix
338 width, height);
339 }
340
341 // Convert J422 to ARGB.
342 LIBYUV_API
J422ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)343 int J422ToARGB(const uint8_t* src_y,
344 int src_stride_y,
345 const uint8_t* src_u,
346 int src_stride_u,
347 const uint8_t* src_v,
348 int src_stride_v,
349 uint8_t* dst_argb,
350 int dst_stride_argb,
351 int width,
352 int height) {
353 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
354 src_stride_v, dst_argb, dst_stride_argb,
355 &kYuvJPEGConstants, width, height);
356 }
357
358 // Convert J422 to ABGR.
359 LIBYUV_API
J422ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)360 int J422ToABGR(const uint8_t* src_y,
361 int src_stride_y,
362 const uint8_t* src_u,
363 int src_stride_u,
364 const uint8_t* src_v,
365 int src_stride_v,
366 uint8_t* dst_abgr,
367 int dst_stride_abgr,
368 int width,
369 int height) {
370 return I422ToARGBMatrix(src_y, src_stride_y, src_v,
371 src_stride_v, // Swap U and V
372 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
373 &kYvuJPEGConstants, // Use Yvu matrix
374 width, height);
375 }
376
377 // Convert H422 to ARGB.
378 LIBYUV_API
H422ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)379 int H422ToARGB(const uint8_t* src_y,
380 int src_stride_y,
381 const uint8_t* src_u,
382 int src_stride_u,
383 const uint8_t* src_v,
384 int src_stride_v,
385 uint8_t* dst_argb,
386 int dst_stride_argb,
387 int width,
388 int height) {
389 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
390 src_stride_v, dst_argb, dst_stride_argb,
391 &kYuvH709Constants, width, height);
392 }
393
394 // Convert H422 to ABGR.
395 LIBYUV_API
H422ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)396 int H422ToABGR(const uint8_t* src_y,
397 int src_stride_y,
398 const uint8_t* src_u,
399 int src_stride_u,
400 const uint8_t* src_v,
401 int src_stride_v,
402 uint8_t* dst_abgr,
403 int dst_stride_abgr,
404 int width,
405 int height) {
406 return I422ToARGBMatrix(src_y, src_stride_y, src_v,
407 src_stride_v, // Swap U and V
408 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
409 &kYvuH709Constants, // Use Yvu matrix
410 width, height);
411 }
412
413 // Convert 10 bit YUV to ARGB with matrix
414 // TODO(fbarchard): Consider passing scale multiplier to I210ToARGB to
415 // multiply 10 bit yuv into high bits to allow any number of bits.
I010ToAR30Matrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height)416 static int I010ToAR30Matrix(const uint16_t* src_y,
417 int src_stride_y,
418 const uint16_t* src_u,
419 int src_stride_u,
420 const uint16_t* src_v,
421 int src_stride_v,
422 uint8_t* dst_ar30,
423 int dst_stride_ar30,
424 const struct YuvConstants* yuvconstants,
425 int width,
426 int height) {
427 int y;
428 void (*I210ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
429 const uint16_t* v_buf, uint8_t* rgb_buf,
430 const struct YuvConstants* yuvconstants, int width) =
431 I210ToAR30Row_C;
432 if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
433 return -1;
434 }
435 // Negative height means invert the image.
436 if (height < 0) {
437 height = -height;
438 dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
439 dst_stride_ar30 = -dst_stride_ar30;
440 }
441 #if defined(HAS_I210TOAR30ROW_SSSE3)
442 if (TestCpuFlag(kCpuHasSSSE3)) {
443 I210ToAR30Row = I210ToAR30Row_Any_SSSE3;
444 if (IS_ALIGNED(width, 8)) {
445 I210ToAR30Row = I210ToAR30Row_SSSE3;
446 }
447 }
448 #endif
449 #if defined(HAS_I210TOAR30ROW_AVX2)
450 if (TestCpuFlag(kCpuHasAVX2)) {
451 I210ToAR30Row = I210ToAR30Row_Any_AVX2;
452 if (IS_ALIGNED(width, 16)) {
453 I210ToAR30Row = I210ToAR30Row_AVX2;
454 }
455 }
456 #endif
457 for (y = 0; y < height; ++y) {
458 I210ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
459 dst_ar30 += dst_stride_ar30;
460 src_y += src_stride_y;
461 if (y & 1) {
462 src_u += src_stride_u;
463 src_v += src_stride_v;
464 }
465 }
466 return 0;
467 }
468
469 // Convert I010 to AR30.
470 LIBYUV_API
I010ToAR30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,int width,int height)471 int I010ToAR30(const uint16_t* src_y,
472 int src_stride_y,
473 const uint16_t* src_u,
474 int src_stride_u,
475 const uint16_t* src_v,
476 int src_stride_v,
477 uint8_t* dst_ar30,
478 int dst_stride_ar30,
479 int width,
480 int height) {
481 return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
482 src_stride_v, dst_ar30, dst_stride_ar30,
483 &kYuvI601Constants, width, height);
484 }
485
486 // Convert H010 to AR30.
487 LIBYUV_API
H010ToAR30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,int width,int height)488 int H010ToAR30(const uint16_t* src_y,
489 int src_stride_y,
490 const uint16_t* src_u,
491 int src_stride_u,
492 const uint16_t* src_v,
493 int src_stride_v,
494 uint8_t* dst_ar30,
495 int dst_stride_ar30,
496 int width,
497 int height) {
498 return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
499 src_stride_v, dst_ar30, dst_stride_ar30,
500 &kYuvH709Constants, width, height);
501 }
502
503 // Convert I010 to AB30.
504 LIBYUV_API
I010ToAB30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)505 int I010ToAB30(const uint16_t* src_y,
506 int src_stride_y,
507 const uint16_t* src_u,
508 int src_stride_u,
509 const uint16_t* src_v,
510 int src_stride_v,
511 uint8_t* dst_ab30,
512 int dst_stride_ab30,
513 int width,
514 int height) {
515 return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
516 src_stride_u, dst_ab30, dst_stride_ab30,
517 &kYvuI601Constants, width, height);
518 }
519
520 // Convert H010 to AB30.
521 LIBYUV_API
H010ToAB30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)522 int H010ToAB30(const uint16_t* src_y,
523 int src_stride_y,
524 const uint16_t* src_u,
525 int src_stride_u,
526 const uint16_t* src_v,
527 int src_stride_v,
528 uint8_t* dst_ab30,
529 int dst_stride_ab30,
530 int width,
531 int height) {
532 return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
533 src_stride_u, dst_ab30, dst_stride_ab30,
534 &kYvuH709Constants, width, height);
535 }
536
537 // Convert 10 bit YUV to ARGB with matrix
I010ToARGBMatrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)538 static int I010ToARGBMatrix(const uint16_t* src_y,
539 int src_stride_y,
540 const uint16_t* src_u,
541 int src_stride_u,
542 const uint16_t* src_v,
543 int src_stride_v,
544 uint8_t* dst_argb,
545 int dst_stride_argb,
546 const struct YuvConstants* yuvconstants,
547 int width,
548 int height) {
549 int y;
550 void (*I210ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
551 const uint16_t* v_buf, uint8_t* rgb_buf,
552 const struct YuvConstants* yuvconstants, int width) =
553 I210ToARGBRow_C;
554 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
555 return -1;
556 }
557 // Negative height means invert the image.
558 if (height < 0) {
559 height = -height;
560 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
561 dst_stride_argb = -dst_stride_argb;
562 }
563 #if defined(HAS_I210TOARGBROW_SSSE3)
564 if (TestCpuFlag(kCpuHasSSSE3)) {
565 I210ToARGBRow = I210ToARGBRow_Any_SSSE3;
566 if (IS_ALIGNED(width, 8)) {
567 I210ToARGBRow = I210ToARGBRow_SSSE3;
568 }
569 }
570 #endif
571 #if defined(HAS_I210TOARGBROW_AVX2)
572 if (TestCpuFlag(kCpuHasAVX2)) {
573 I210ToARGBRow = I210ToARGBRow_Any_AVX2;
574 if (IS_ALIGNED(width, 16)) {
575 I210ToARGBRow = I210ToARGBRow_AVX2;
576 }
577 }
578 #endif
579 for (y = 0; y < height; ++y) {
580 I210ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
581 dst_argb += dst_stride_argb;
582 src_y += src_stride_y;
583 if (y & 1) {
584 src_u += src_stride_u;
585 src_v += src_stride_v;
586 }
587 }
588 return 0;
589 }
590
591 // Convert I010 to ARGB.
592 LIBYUV_API
I010ToARGB(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)593 int I010ToARGB(const uint16_t* src_y,
594 int src_stride_y,
595 const uint16_t* src_u,
596 int src_stride_u,
597 const uint16_t* src_v,
598 int src_stride_v,
599 uint8_t* dst_argb,
600 int dst_stride_argb,
601 int width,
602 int height) {
603 return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
604 src_stride_v, dst_argb, dst_stride_argb,
605 &kYuvI601Constants, width, height);
606 }
607
608 // Convert I010 to ABGR.
609 LIBYUV_API
I010ToABGR(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)610 int I010ToABGR(const uint16_t* src_y,
611 int src_stride_y,
612 const uint16_t* src_u,
613 int src_stride_u,
614 const uint16_t* src_v,
615 int src_stride_v,
616 uint8_t* dst_abgr,
617 int dst_stride_abgr,
618 int width,
619 int height) {
620 return I010ToARGBMatrix(src_y, src_stride_y, src_v,
621 src_stride_v, // Swap U and V
622 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
623 &kYvuI601Constants, // Use Yvu matrix
624 width, height);
625 }
626
627 // Convert H010 to ARGB.
628 LIBYUV_API
H010ToARGB(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)629 int H010ToARGB(const uint16_t* src_y,
630 int src_stride_y,
631 const uint16_t* src_u,
632 int src_stride_u,
633 const uint16_t* src_v,
634 int src_stride_v,
635 uint8_t* dst_argb,
636 int dst_stride_argb,
637 int width,
638 int height) {
639 return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
640 src_stride_v, dst_argb, dst_stride_argb,
641 &kYuvH709Constants, width, height);
642 }
643
644 // Convert H010 to ABGR.
645 LIBYUV_API
H010ToABGR(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)646 int H010ToABGR(const uint16_t* src_y,
647 int src_stride_y,
648 const uint16_t* src_u,
649 int src_stride_u,
650 const uint16_t* src_v,
651 int src_stride_v,
652 uint8_t* dst_abgr,
653 int dst_stride_abgr,
654 int width,
655 int height) {
656 return I010ToARGBMatrix(src_y, src_stride_y, src_v,
657 src_stride_v, // Swap U and V
658 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
659 &kYvuH709Constants, // Use Yvu matrix
660 width, height);
661 }
662
663 // Convert I444 to ARGB with matrix
I444ToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)664 static int I444ToARGBMatrix(const uint8_t* src_y,
665 int src_stride_y,
666 const uint8_t* src_u,
667 int src_stride_u,
668 const uint8_t* src_v,
669 int src_stride_v,
670 uint8_t* dst_argb,
671 int dst_stride_argb,
672 const struct YuvConstants* yuvconstants,
673 int width,
674 int height) {
675 int y;
676 void (*I444ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
677 const uint8_t* v_buf, uint8_t* rgb_buf,
678 const struct YuvConstants* yuvconstants, int width) =
679 I444ToARGBRow_C;
680 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
681 return -1;
682 }
683 // Negative height means invert the image.
684 if (height < 0) {
685 height = -height;
686 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
687 dst_stride_argb = -dst_stride_argb;
688 }
689 // Coalesce rows.
690 if (src_stride_y == width && src_stride_u == width && src_stride_v == width &&
691 dst_stride_argb == width * 4) {
692 width *= height;
693 height = 1;
694 src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
695 }
696 #if defined(HAS_I444TOARGBROW_SSSE3)
697 if (TestCpuFlag(kCpuHasSSSE3)) {
698 I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
699 if (IS_ALIGNED(width, 8)) {
700 I444ToARGBRow = I444ToARGBRow_SSSE3;
701 }
702 }
703 #endif
704 #if defined(HAS_I444TOARGBROW_AVX2)
705 if (TestCpuFlag(kCpuHasAVX2)) {
706 I444ToARGBRow = I444ToARGBRow_Any_AVX2;
707 if (IS_ALIGNED(width, 16)) {
708 I444ToARGBRow = I444ToARGBRow_AVX2;
709 }
710 }
711 #endif
712 #if defined(HAS_I444TOARGBROW_NEON)
713 if (TestCpuFlag(kCpuHasNEON)) {
714 I444ToARGBRow = I444ToARGBRow_Any_NEON;
715 if (IS_ALIGNED(width, 8)) {
716 I444ToARGBRow = I444ToARGBRow_NEON;
717 }
718 }
719 #endif
720 #if defined(HAS_I444TOARGBROW_MSA)
721 if (TestCpuFlag(kCpuHasMSA)) {
722 I444ToARGBRow = I444ToARGBRow_Any_MSA;
723 if (IS_ALIGNED(width, 8)) {
724 I444ToARGBRow = I444ToARGBRow_MSA;
725 }
726 }
727 #endif
728
729 for (y = 0; y < height; ++y) {
730 I444ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
731 dst_argb += dst_stride_argb;
732 src_y += src_stride_y;
733 src_u += src_stride_u;
734 src_v += src_stride_v;
735 }
736 return 0;
737 }
738
739 // Convert I444 to ARGB.
740 LIBYUV_API
I444ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)741 int I444ToARGB(const uint8_t* src_y,
742 int src_stride_y,
743 const uint8_t* src_u,
744 int src_stride_u,
745 const uint8_t* src_v,
746 int src_stride_v,
747 uint8_t* dst_argb,
748 int dst_stride_argb,
749 int width,
750 int height) {
751 return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
752 src_stride_v, dst_argb, dst_stride_argb,
753 &kYuvI601Constants, width, height);
754 }
755
756 // Convert I444 to ABGR.
757 LIBYUV_API
I444ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)758 int I444ToABGR(const uint8_t* src_y,
759 int src_stride_y,
760 const uint8_t* src_u,
761 int src_stride_u,
762 const uint8_t* src_v,
763 int src_stride_v,
764 uint8_t* dst_abgr,
765 int dst_stride_abgr,
766 int width,
767 int height) {
768 return I444ToARGBMatrix(src_y, src_stride_y, src_v,
769 src_stride_v, // Swap U and V
770 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
771 &kYvuI601Constants, // Use Yvu matrix
772 width, height);
773 }
774
775 // Convert J444 to ARGB.
776 LIBYUV_API
J444ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)777 int J444ToARGB(const uint8_t* src_y,
778 int src_stride_y,
779 const uint8_t* src_u,
780 int src_stride_u,
781 const uint8_t* src_v,
782 int src_stride_v,
783 uint8_t* dst_argb,
784 int dst_stride_argb,
785 int width,
786 int height) {
787 return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
788 src_stride_v, dst_argb, dst_stride_argb,
789 &kYuvJPEGConstants, width, height);
790 }
791
792 // Convert I420 with Alpha to preattenuated ARGB.
I420AlphaToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,const uint8_t * src_a,int src_stride_a,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,int attenuate)793 static int I420AlphaToARGBMatrix(const uint8_t* src_y,
794 int src_stride_y,
795 const uint8_t* src_u,
796 int src_stride_u,
797 const uint8_t* src_v,
798 int src_stride_v,
799 const uint8_t* src_a,
800 int src_stride_a,
801 uint8_t* dst_argb,
802 int dst_stride_argb,
803 const struct YuvConstants* yuvconstants,
804 int width,
805 int height,
806 int attenuate) {
807 int y;
808 void (*I422AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
809 const uint8_t* v_buf, const uint8_t* a_buf,
810 uint8_t* dst_argb,
811 const struct YuvConstants* yuvconstants,
812 int width) = I422AlphaToARGBRow_C;
813 void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
814 int width) = ARGBAttenuateRow_C;
815 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
816 return -1;
817 }
818 // Negative height means invert the image.
819 if (height < 0) {
820 height = -height;
821 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
822 dst_stride_argb = -dst_stride_argb;
823 }
824 #if defined(HAS_I422ALPHATOARGBROW_SSSE3)
825 if (TestCpuFlag(kCpuHasSSSE3)) {
826 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_SSSE3;
827 if (IS_ALIGNED(width, 8)) {
828 I422AlphaToARGBRow = I422AlphaToARGBRow_SSSE3;
829 }
830 }
831 #endif
832 #if defined(HAS_I422ALPHATOARGBROW_AVX2)
833 if (TestCpuFlag(kCpuHasAVX2)) {
834 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_AVX2;
835 if (IS_ALIGNED(width, 16)) {
836 I422AlphaToARGBRow = I422AlphaToARGBRow_AVX2;
837 }
838 }
839 #endif
840 #if defined(HAS_I422ALPHATOARGBROW_NEON)
841 if (TestCpuFlag(kCpuHasNEON)) {
842 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_NEON;
843 if (IS_ALIGNED(width, 8)) {
844 I422AlphaToARGBRow = I422AlphaToARGBRow_NEON;
845 }
846 }
847 #endif
848 #if defined(HAS_I422ALPHATOARGBROW_MSA)
849 if (TestCpuFlag(kCpuHasMSA)) {
850 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_MSA;
851 if (IS_ALIGNED(width, 8)) {
852 I422AlphaToARGBRow = I422AlphaToARGBRow_MSA;
853 }
854 }
855 #endif
856 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
857 if (TestCpuFlag(kCpuHasSSSE3)) {
858 ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
859 if (IS_ALIGNED(width, 4)) {
860 ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
861 }
862 }
863 #endif
864 #if defined(HAS_ARGBATTENUATEROW_AVX2)
865 if (TestCpuFlag(kCpuHasAVX2)) {
866 ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
867 if (IS_ALIGNED(width, 8)) {
868 ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
869 }
870 }
871 #endif
872 #if defined(HAS_ARGBATTENUATEROW_NEON)
873 if (TestCpuFlag(kCpuHasNEON)) {
874 ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
875 if (IS_ALIGNED(width, 8)) {
876 ARGBAttenuateRow = ARGBAttenuateRow_NEON;
877 }
878 }
879 #endif
880 #if defined(HAS_ARGBATTENUATEROW_MSA)
881 if (TestCpuFlag(kCpuHasMSA)) {
882 ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
883 if (IS_ALIGNED(width, 8)) {
884 ARGBAttenuateRow = ARGBAttenuateRow_MSA;
885 }
886 }
887 #endif
888 #if defined(HAS_ARGBATTENUATEROW_MMI)
889 if (TestCpuFlag(kCpuHasMMI)) {
890 ARGBAttenuateRow = ARGBAttenuateRow_Any_MMI;
891 if (IS_ALIGNED(width, 2)) {
892 ARGBAttenuateRow = ARGBAttenuateRow_MMI;
893 }
894 }
895 #endif
896
897 for (y = 0; y < height; ++y) {
898 I422AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
899 width);
900 if (attenuate) {
901 ARGBAttenuateRow(dst_argb, dst_argb, width);
902 }
903 dst_argb += dst_stride_argb;
904 src_a += src_stride_a;
905 src_y += src_stride_y;
906 if (y & 1) {
907 src_u += src_stride_u;
908 src_v += src_stride_v;
909 }
910 }
911 return 0;
912 }
913
914 // Convert I420 with Alpha to ARGB.
915 LIBYUV_API
I420AlphaToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,const uint8_t * src_a,int src_stride_a,uint8_t * dst_argb,int dst_stride_argb,int width,int height,int attenuate)916 int I420AlphaToARGB(const uint8_t* src_y,
917 int src_stride_y,
918 const uint8_t* src_u,
919 int src_stride_u,
920 const uint8_t* src_v,
921 int src_stride_v,
922 const uint8_t* src_a,
923 int src_stride_a,
924 uint8_t* dst_argb,
925 int dst_stride_argb,
926 int width,
927 int height,
928 int attenuate) {
929 return I420AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
930 src_stride_v, src_a, src_stride_a, dst_argb,
931 dst_stride_argb, &kYuvI601Constants, width,
932 height, attenuate);
933 }
934
935 // Convert I420 with Alpha to ABGR.
936 LIBYUV_API
I420AlphaToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,const uint8_t * src_a,int src_stride_a,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height,int attenuate)937 int I420AlphaToABGR(const uint8_t* src_y,
938 int src_stride_y,
939 const uint8_t* src_u,
940 int src_stride_u,
941 const uint8_t* src_v,
942 int src_stride_v,
943 const uint8_t* src_a,
944 int src_stride_a,
945 uint8_t* dst_abgr,
946 int dst_stride_abgr,
947 int width,
948 int height,
949 int attenuate) {
950 return I420AlphaToARGBMatrix(
951 src_y, src_stride_y, src_v, src_stride_v, // Swap U and V
952 src_u, src_stride_u, src_a, src_stride_a, dst_abgr, dst_stride_abgr,
953 &kYvuI601Constants, // Use Yvu matrix
954 width, height, attenuate);
955 }
956
957 // Convert I400 to ARGB.
958 LIBYUV_API
I400ToARGB(const uint8_t * src_y,int src_stride_y,uint8_t * dst_argb,int dst_stride_argb,int width,int height)959 int I400ToARGB(const uint8_t* src_y,
960 int src_stride_y,
961 uint8_t* dst_argb,
962 int dst_stride_argb,
963 int width,
964 int height) {
965 int y;
966 void (*I400ToARGBRow)(const uint8_t* y_buf, uint8_t* rgb_buf, int width) =
967 I400ToARGBRow_C;
968 if (!src_y || !dst_argb || width <= 0 || height == 0) {
969 return -1;
970 }
971 // Negative height means invert the image.
972 if (height < 0) {
973 height = -height;
974 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
975 dst_stride_argb = -dst_stride_argb;
976 }
977 // Coalesce rows.
978 if (src_stride_y == width && dst_stride_argb == width * 4) {
979 width *= height;
980 height = 1;
981 src_stride_y = dst_stride_argb = 0;
982 }
983 #if defined(HAS_I400TOARGBROW_SSE2)
984 if (TestCpuFlag(kCpuHasSSE2)) {
985 I400ToARGBRow = I400ToARGBRow_Any_SSE2;
986 if (IS_ALIGNED(width, 8)) {
987 I400ToARGBRow = I400ToARGBRow_SSE2;
988 }
989 }
990 #endif
991 #if defined(HAS_I400TOARGBROW_AVX2)
992 if (TestCpuFlag(kCpuHasAVX2)) {
993 I400ToARGBRow = I400ToARGBRow_Any_AVX2;
994 if (IS_ALIGNED(width, 16)) {
995 I400ToARGBRow = I400ToARGBRow_AVX2;
996 }
997 }
998 #endif
999 #if defined(HAS_I400TOARGBROW_NEON)
1000 if (TestCpuFlag(kCpuHasNEON)) {
1001 I400ToARGBRow = I400ToARGBRow_Any_NEON;
1002 if (IS_ALIGNED(width, 8)) {
1003 I400ToARGBRow = I400ToARGBRow_NEON;
1004 }
1005 }
1006 #endif
1007 #if defined(HAS_I400TOARGBROW_MSA)
1008 if (TestCpuFlag(kCpuHasMSA)) {
1009 I400ToARGBRow = I400ToARGBRow_Any_MSA;
1010 if (IS_ALIGNED(width, 16)) {
1011 I400ToARGBRow = I400ToARGBRow_MSA;
1012 }
1013 }
1014 #endif
1015 #if defined(HAS_I400TOARGBROW_MMI)
1016 if (TestCpuFlag(kCpuHasMMI)) {
1017 I400ToARGBRow = I400ToARGBRow_Any_MMI;
1018 if (IS_ALIGNED(width, 8)) {
1019 I400ToARGBRow = I400ToARGBRow_MMI;
1020 }
1021 }
1022 #endif
1023
1024 for (y = 0; y < height; ++y) {
1025 I400ToARGBRow(src_y, dst_argb, width);
1026 dst_argb += dst_stride_argb;
1027 src_y += src_stride_y;
1028 }
1029 return 0;
1030 }
1031
1032 // Convert J400 to ARGB.
1033 LIBYUV_API
J400ToARGB(const uint8_t * src_y,int src_stride_y,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1034 int J400ToARGB(const uint8_t* src_y,
1035 int src_stride_y,
1036 uint8_t* dst_argb,
1037 int dst_stride_argb,
1038 int width,
1039 int height) {
1040 int y;
1041 void (*J400ToARGBRow)(const uint8_t* src_y, uint8_t* dst_argb, int width) =
1042 J400ToARGBRow_C;
1043 if (!src_y || !dst_argb || width <= 0 || height == 0) {
1044 return -1;
1045 }
1046 // Negative height means invert the image.
1047 if (height < 0) {
1048 height = -height;
1049 src_y = src_y + (height - 1) * src_stride_y;
1050 src_stride_y = -src_stride_y;
1051 }
1052 // Coalesce rows.
1053 if (src_stride_y == width && dst_stride_argb == width * 4) {
1054 width *= height;
1055 height = 1;
1056 src_stride_y = dst_stride_argb = 0;
1057 }
1058 #if defined(HAS_J400TOARGBROW_SSE2)
1059 if (TestCpuFlag(kCpuHasSSE2)) {
1060 J400ToARGBRow = J400ToARGBRow_Any_SSE2;
1061 if (IS_ALIGNED(width, 8)) {
1062 J400ToARGBRow = J400ToARGBRow_SSE2;
1063 }
1064 }
1065 #endif
1066 #if defined(HAS_J400TOARGBROW_AVX2)
1067 if (TestCpuFlag(kCpuHasAVX2)) {
1068 J400ToARGBRow = J400ToARGBRow_Any_AVX2;
1069 if (IS_ALIGNED(width, 16)) {
1070 J400ToARGBRow = J400ToARGBRow_AVX2;
1071 }
1072 }
1073 #endif
1074 #if defined(HAS_J400TOARGBROW_NEON)
1075 if (TestCpuFlag(kCpuHasNEON)) {
1076 J400ToARGBRow = J400ToARGBRow_Any_NEON;
1077 if (IS_ALIGNED(width, 8)) {
1078 J400ToARGBRow = J400ToARGBRow_NEON;
1079 }
1080 }
1081 #endif
1082 #if defined(HAS_J400TOARGBROW_MSA)
1083 if (TestCpuFlag(kCpuHasMSA)) {
1084 J400ToARGBRow = J400ToARGBRow_Any_MSA;
1085 if (IS_ALIGNED(width, 16)) {
1086 J400ToARGBRow = J400ToARGBRow_MSA;
1087 }
1088 }
1089 #endif
1090 #if defined(HAS_J400TOARGBROW_MMI)
1091 if (TestCpuFlag(kCpuHasMMI)) {
1092 J400ToARGBRow = J400ToARGBRow_Any_MMI;
1093 if (IS_ALIGNED(width, 4)) {
1094 J400ToARGBRow = J400ToARGBRow_MMI;
1095 }
1096 }
1097 #endif
1098 for (y = 0; y < height; ++y) {
1099 J400ToARGBRow(src_y, dst_argb, width);
1100 src_y += src_stride_y;
1101 dst_argb += dst_stride_argb;
1102 }
1103 return 0;
1104 }
1105
1106 // Shuffle table for converting BGRA to ARGB.
1107 static const uvec8 kShuffleMaskBGRAToARGB = {
1108 3u, 2u, 1u, 0u, 7u, 6u, 5u, 4u, 11u, 10u, 9u, 8u, 15u, 14u, 13u, 12u};
1109
1110 // Shuffle table for converting ABGR to ARGB.
1111 static const uvec8 kShuffleMaskABGRToARGB = {
1112 2u, 1u, 0u, 3u, 6u, 5u, 4u, 7u, 10u, 9u, 8u, 11u, 14u, 13u, 12u, 15u};
1113
1114 // Shuffle table for converting RGBA to ARGB.
1115 static const uvec8 kShuffleMaskRGBAToARGB = {
1116 1u, 2u, 3u, 0u, 5u, 6u, 7u, 4u, 9u, 10u, 11u, 8u, 13u, 14u, 15u, 12u};
1117
1118 // Convert BGRA to ARGB.
1119 LIBYUV_API
BGRAToARGB(const uint8_t * src_bgra,int src_stride_bgra,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1120 int BGRAToARGB(const uint8_t* src_bgra,
1121 int src_stride_bgra,
1122 uint8_t* dst_argb,
1123 int dst_stride_argb,
1124 int width,
1125 int height) {
1126 return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb,
1127 (const uint8_t*)(&kShuffleMaskBGRAToARGB), width, height);
1128 }
1129
1130 // Convert ARGB to BGRA (same as BGRAToARGB).
1131 LIBYUV_API
ARGBToBGRA(const uint8_t * src_bgra,int src_stride_bgra,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1132 int ARGBToBGRA(const uint8_t* src_bgra,
1133 int src_stride_bgra,
1134 uint8_t* dst_argb,
1135 int dst_stride_argb,
1136 int width,
1137 int height) {
1138 return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb,
1139 (const uint8_t*)(&kShuffleMaskBGRAToARGB), width, height);
1140 }
1141
1142 // Convert ABGR to ARGB.
1143 LIBYUV_API
ABGRToARGB(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1144 int ABGRToARGB(const uint8_t* src_abgr,
1145 int src_stride_abgr,
1146 uint8_t* dst_argb,
1147 int dst_stride_argb,
1148 int width,
1149 int height) {
1150 return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb,
1151 (const uint8_t*)(&kShuffleMaskABGRToARGB), width, height);
1152 }
1153
1154 // Convert ARGB to ABGR to (same as ABGRToARGB).
1155 LIBYUV_API
ARGBToABGR(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1156 int ARGBToABGR(const uint8_t* src_abgr,
1157 int src_stride_abgr,
1158 uint8_t* dst_argb,
1159 int dst_stride_argb,
1160 int width,
1161 int height) {
1162 return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb,
1163 (const uint8_t*)(&kShuffleMaskABGRToARGB), width, height);
1164 }
1165
1166 // Convert RGBA to ARGB.
1167 LIBYUV_API
RGBAToARGB(const uint8_t * src_rgba,int src_stride_rgba,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1168 int RGBAToARGB(const uint8_t* src_rgba,
1169 int src_stride_rgba,
1170 uint8_t* dst_argb,
1171 int dst_stride_argb,
1172 int width,
1173 int height) {
1174 return ARGBShuffle(src_rgba, src_stride_rgba, dst_argb, dst_stride_argb,
1175 (const uint8_t*)(&kShuffleMaskRGBAToARGB), width, height);
1176 }
1177
1178 // Convert RGB24 to ARGB.
1179 LIBYUV_API
RGB24ToARGB(const uint8_t * src_rgb24,int src_stride_rgb24,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1180 int RGB24ToARGB(const uint8_t* src_rgb24,
1181 int src_stride_rgb24,
1182 uint8_t* dst_argb,
1183 int dst_stride_argb,
1184 int width,
1185 int height) {
1186 int y;
1187 void (*RGB24ToARGBRow)(const uint8_t* src_rgb, uint8_t* dst_argb, int width) =
1188 RGB24ToARGBRow_C;
1189 if (!src_rgb24 || !dst_argb || width <= 0 || height == 0) {
1190 return -1;
1191 }
1192 // Negative height means invert the image.
1193 if (height < 0) {
1194 height = -height;
1195 src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24;
1196 src_stride_rgb24 = -src_stride_rgb24;
1197 }
1198 // Coalesce rows.
1199 if (src_stride_rgb24 == width * 3 && dst_stride_argb == width * 4) {
1200 width *= height;
1201 height = 1;
1202 src_stride_rgb24 = dst_stride_argb = 0;
1203 }
1204 #if defined(HAS_RGB24TOARGBROW_SSSE3)
1205 if (TestCpuFlag(kCpuHasSSSE3)) {
1206 RGB24ToARGBRow = RGB24ToARGBRow_Any_SSSE3;
1207 if (IS_ALIGNED(width, 16)) {
1208 RGB24ToARGBRow = RGB24ToARGBRow_SSSE3;
1209 }
1210 }
1211 #endif
1212 #if defined(HAS_RGB24TOARGBROW_NEON)
1213 if (TestCpuFlag(kCpuHasNEON)) {
1214 RGB24ToARGBRow = RGB24ToARGBRow_Any_NEON;
1215 if (IS_ALIGNED(width, 8)) {
1216 RGB24ToARGBRow = RGB24ToARGBRow_NEON;
1217 }
1218 }
1219 #endif
1220 #if defined(HAS_RGB24TOARGBROW_MSA)
1221 if (TestCpuFlag(kCpuHasMSA)) {
1222 RGB24ToARGBRow = RGB24ToARGBRow_Any_MSA;
1223 if (IS_ALIGNED(width, 16)) {
1224 RGB24ToARGBRow = RGB24ToARGBRow_MSA;
1225 }
1226 }
1227 #endif
1228 #if defined(HAS_RGB24TOARGBROW_MMI)
1229 if (TestCpuFlag(kCpuHasMMI)) {
1230 RGB24ToARGBRow = RGB24ToARGBRow_Any_MMI;
1231 if (IS_ALIGNED(width, 4)) {
1232 RGB24ToARGBRow = RGB24ToARGBRow_MMI;
1233 }
1234 }
1235 #endif
1236
1237 for (y = 0; y < height; ++y) {
1238 RGB24ToARGBRow(src_rgb24, dst_argb, width);
1239 src_rgb24 += src_stride_rgb24;
1240 dst_argb += dst_stride_argb;
1241 }
1242 return 0;
1243 }
1244
1245 // Convert RAW to ARGB.
1246 LIBYUV_API
RAWToARGB(const uint8_t * src_raw,int src_stride_raw,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1247 int RAWToARGB(const uint8_t* src_raw,
1248 int src_stride_raw,
1249 uint8_t* dst_argb,
1250 int dst_stride_argb,
1251 int width,
1252 int height) {
1253 int y;
1254 void (*RAWToARGBRow)(const uint8_t* src_rgb, uint8_t* dst_argb, int width) =
1255 RAWToARGBRow_C;
1256 if (!src_raw || !dst_argb || width <= 0 || height == 0) {
1257 return -1;
1258 }
1259 // Negative height means invert the image.
1260 if (height < 0) {
1261 height = -height;
1262 src_raw = src_raw + (height - 1) * src_stride_raw;
1263 src_stride_raw = -src_stride_raw;
1264 }
1265 // Coalesce rows.
1266 if (src_stride_raw == width * 3 && dst_stride_argb == width * 4) {
1267 width *= height;
1268 height = 1;
1269 src_stride_raw = dst_stride_argb = 0;
1270 }
1271 #if defined(HAS_RAWTOARGBROW_SSSE3)
1272 if (TestCpuFlag(kCpuHasSSSE3)) {
1273 RAWToARGBRow = RAWToARGBRow_Any_SSSE3;
1274 if (IS_ALIGNED(width, 16)) {
1275 RAWToARGBRow = RAWToARGBRow_SSSE3;
1276 }
1277 }
1278 #endif
1279 #if defined(HAS_RAWTOARGBROW_NEON)
1280 if (TestCpuFlag(kCpuHasNEON)) {
1281 RAWToARGBRow = RAWToARGBRow_Any_NEON;
1282 if (IS_ALIGNED(width, 8)) {
1283 RAWToARGBRow = RAWToARGBRow_NEON;
1284 }
1285 }
1286 #endif
1287 #if defined(HAS_RAWTOARGBROW_MSA)
1288 if (TestCpuFlag(kCpuHasMSA)) {
1289 RAWToARGBRow = RAWToARGBRow_Any_MSA;
1290 if (IS_ALIGNED(width, 16)) {
1291 RAWToARGBRow = RAWToARGBRow_MSA;
1292 }
1293 }
1294 #endif
1295 #if defined(HAS_RAWTOARGBROW_MMI)
1296 if (TestCpuFlag(kCpuHasMMI)) {
1297 RAWToARGBRow = RAWToARGBRow_Any_MMI;
1298 if (IS_ALIGNED(width, 4)) {
1299 RAWToARGBRow = RAWToARGBRow_MMI;
1300 }
1301 }
1302 #endif
1303
1304 for (y = 0; y < height; ++y) {
1305 RAWToARGBRow(src_raw, dst_argb, width);
1306 src_raw += src_stride_raw;
1307 dst_argb += dst_stride_argb;
1308 }
1309 return 0;
1310 }
1311
1312 // Convert RGB565 to ARGB.
1313 LIBYUV_API
RGB565ToARGB(const uint8_t * src_rgb565,int src_stride_rgb565,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1314 int RGB565ToARGB(const uint8_t* src_rgb565,
1315 int src_stride_rgb565,
1316 uint8_t* dst_argb,
1317 int dst_stride_argb,
1318 int width,
1319 int height) {
1320 int y;
1321 void (*RGB565ToARGBRow)(const uint8_t* src_rgb565, uint8_t* dst_argb,
1322 int width) = RGB565ToARGBRow_C;
1323 if (!src_rgb565 || !dst_argb || width <= 0 || height == 0) {
1324 return -1;
1325 }
1326 // Negative height means invert the image.
1327 if (height < 0) {
1328 height = -height;
1329 src_rgb565 = src_rgb565 + (height - 1) * src_stride_rgb565;
1330 src_stride_rgb565 = -src_stride_rgb565;
1331 }
1332 // Coalesce rows.
1333 if (src_stride_rgb565 == width * 2 && dst_stride_argb == width * 4) {
1334 width *= height;
1335 height = 1;
1336 src_stride_rgb565 = dst_stride_argb = 0;
1337 }
1338 #if defined(HAS_RGB565TOARGBROW_SSE2)
1339 if (TestCpuFlag(kCpuHasSSE2)) {
1340 RGB565ToARGBRow = RGB565ToARGBRow_Any_SSE2;
1341 if (IS_ALIGNED(width, 8)) {
1342 RGB565ToARGBRow = RGB565ToARGBRow_SSE2;
1343 }
1344 }
1345 #endif
1346 #if defined(HAS_RGB565TOARGBROW_AVX2)
1347 if (TestCpuFlag(kCpuHasAVX2)) {
1348 RGB565ToARGBRow = RGB565ToARGBRow_Any_AVX2;
1349 if (IS_ALIGNED(width, 16)) {
1350 RGB565ToARGBRow = RGB565ToARGBRow_AVX2;
1351 }
1352 }
1353 #endif
1354 #if defined(HAS_RGB565TOARGBROW_NEON)
1355 if (TestCpuFlag(kCpuHasNEON)) {
1356 RGB565ToARGBRow = RGB565ToARGBRow_Any_NEON;
1357 if (IS_ALIGNED(width, 8)) {
1358 RGB565ToARGBRow = RGB565ToARGBRow_NEON;
1359 }
1360 }
1361 #endif
1362 #if defined(HAS_RGB565TOARGBROW_MSA)
1363 if (TestCpuFlag(kCpuHasMSA)) {
1364 RGB565ToARGBRow = RGB565ToARGBRow_Any_MSA;
1365 if (IS_ALIGNED(width, 16)) {
1366 RGB565ToARGBRow = RGB565ToARGBRow_MSA;
1367 }
1368 }
1369 #endif
1370 #if defined(HAS_RGB565TOARGBROW_MMI)
1371 if (TestCpuFlag(kCpuHasMMI)) {
1372 RGB565ToARGBRow = RGB565ToARGBRow_Any_MMI;
1373 if (IS_ALIGNED(width, 4)) {
1374 RGB565ToARGBRow = RGB565ToARGBRow_MMI;
1375 }
1376 }
1377 #endif
1378
1379 for (y = 0; y < height; ++y) {
1380 RGB565ToARGBRow(src_rgb565, dst_argb, width);
1381 src_rgb565 += src_stride_rgb565;
1382 dst_argb += dst_stride_argb;
1383 }
1384 return 0;
1385 }
1386
1387 // Convert ARGB1555 to ARGB.
1388 LIBYUV_API
ARGB1555ToARGB(const uint8_t * src_argb1555,int src_stride_argb1555,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1389 int ARGB1555ToARGB(const uint8_t* src_argb1555,
1390 int src_stride_argb1555,
1391 uint8_t* dst_argb,
1392 int dst_stride_argb,
1393 int width,
1394 int height) {
1395 int y;
1396 void (*ARGB1555ToARGBRow)(const uint8_t* src_argb1555, uint8_t* dst_argb,
1397 int width) = ARGB1555ToARGBRow_C;
1398 if (!src_argb1555 || !dst_argb || width <= 0 || height == 0) {
1399 return -1;
1400 }
1401 // Negative height means invert the image.
1402 if (height < 0) {
1403 height = -height;
1404 src_argb1555 = src_argb1555 + (height - 1) * src_stride_argb1555;
1405 src_stride_argb1555 = -src_stride_argb1555;
1406 }
1407 // Coalesce rows.
1408 if (src_stride_argb1555 == width * 2 && dst_stride_argb == width * 4) {
1409 width *= height;
1410 height = 1;
1411 src_stride_argb1555 = dst_stride_argb = 0;
1412 }
1413 #if defined(HAS_ARGB1555TOARGBROW_SSE2)
1414 if (TestCpuFlag(kCpuHasSSE2)) {
1415 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_SSE2;
1416 if (IS_ALIGNED(width, 8)) {
1417 ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2;
1418 }
1419 }
1420 #endif
1421 #if defined(HAS_ARGB1555TOARGBROW_AVX2)
1422 if (TestCpuFlag(kCpuHasAVX2)) {
1423 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_AVX2;
1424 if (IS_ALIGNED(width, 16)) {
1425 ARGB1555ToARGBRow = ARGB1555ToARGBRow_AVX2;
1426 }
1427 }
1428 #endif
1429 #if defined(HAS_ARGB1555TOARGBROW_NEON)
1430 if (TestCpuFlag(kCpuHasNEON)) {
1431 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_NEON;
1432 if (IS_ALIGNED(width, 8)) {
1433 ARGB1555ToARGBRow = ARGB1555ToARGBRow_NEON;
1434 }
1435 }
1436 #endif
1437 #if defined(HAS_ARGB1555TOARGBROW_MSA)
1438 if (TestCpuFlag(kCpuHasMSA)) {
1439 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_MSA;
1440 if (IS_ALIGNED(width, 16)) {
1441 ARGB1555ToARGBRow = ARGB1555ToARGBRow_MSA;
1442 }
1443 }
1444 #endif
1445 #if defined(HAS_ARGB1555TOARGBROW_MMI)
1446 if (TestCpuFlag(kCpuHasMMI)) {
1447 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_MMI;
1448 if (IS_ALIGNED(width, 4)) {
1449 ARGB1555ToARGBRow = ARGB1555ToARGBRow_MMI;
1450 }
1451 }
1452 #endif
1453
1454 for (y = 0; y < height; ++y) {
1455 ARGB1555ToARGBRow(src_argb1555, dst_argb, width);
1456 src_argb1555 += src_stride_argb1555;
1457 dst_argb += dst_stride_argb;
1458 }
1459 return 0;
1460 }
1461
1462 // Convert ARGB4444 to ARGB.
1463 LIBYUV_API
ARGB4444ToARGB(const uint8_t * src_argb4444,int src_stride_argb4444,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1464 int ARGB4444ToARGB(const uint8_t* src_argb4444,
1465 int src_stride_argb4444,
1466 uint8_t* dst_argb,
1467 int dst_stride_argb,
1468 int width,
1469 int height) {
1470 int y;
1471 void (*ARGB4444ToARGBRow)(const uint8_t* src_argb4444, uint8_t* dst_argb,
1472 int width) = ARGB4444ToARGBRow_C;
1473 if (!src_argb4444 || !dst_argb || width <= 0 || height == 0) {
1474 return -1;
1475 }
1476 // Negative height means invert the image.
1477 if (height < 0) {
1478 height = -height;
1479 src_argb4444 = src_argb4444 + (height - 1) * src_stride_argb4444;
1480 src_stride_argb4444 = -src_stride_argb4444;
1481 }
1482 // Coalesce rows.
1483 if (src_stride_argb4444 == width * 2 && dst_stride_argb == width * 4) {
1484 width *= height;
1485 height = 1;
1486 src_stride_argb4444 = dst_stride_argb = 0;
1487 }
1488 #if defined(HAS_ARGB4444TOARGBROW_SSE2)
1489 if (TestCpuFlag(kCpuHasSSE2)) {
1490 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_SSE2;
1491 if (IS_ALIGNED(width, 8)) {
1492 ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2;
1493 }
1494 }
1495 #endif
1496 #if defined(HAS_ARGB4444TOARGBROW_AVX2)
1497 if (TestCpuFlag(kCpuHasAVX2)) {
1498 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_AVX2;
1499 if (IS_ALIGNED(width, 16)) {
1500 ARGB4444ToARGBRow = ARGB4444ToARGBRow_AVX2;
1501 }
1502 }
1503 #endif
1504 #if defined(HAS_ARGB4444TOARGBROW_NEON)
1505 if (TestCpuFlag(kCpuHasNEON)) {
1506 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_NEON;
1507 if (IS_ALIGNED(width, 8)) {
1508 ARGB4444ToARGBRow = ARGB4444ToARGBRow_NEON;
1509 }
1510 }
1511 #endif
1512 #if defined(HAS_ARGB4444TOARGBROW_MSA)
1513 if (TestCpuFlag(kCpuHasMSA)) {
1514 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_MSA;
1515 if (IS_ALIGNED(width, 16)) {
1516 ARGB4444ToARGBRow = ARGB4444ToARGBRow_MSA;
1517 }
1518 }
1519 #endif
1520 #if defined(HAS_ARGB4444TOARGBROW_MMI)
1521 if (TestCpuFlag(kCpuHasMMI)) {
1522 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_MMI;
1523 if (IS_ALIGNED(width, 4)) {
1524 ARGB4444ToARGBRow = ARGB4444ToARGBRow_MMI;
1525 }
1526 }
1527 #endif
1528
1529 for (y = 0; y < height; ++y) {
1530 ARGB4444ToARGBRow(src_argb4444, dst_argb, width);
1531 src_argb4444 += src_stride_argb4444;
1532 dst_argb += dst_stride_argb;
1533 }
1534 return 0;
1535 }
1536
1537 // Convert AR30 to ARGB.
1538 LIBYUV_API
AR30ToARGB(const uint8_t * src_ar30,int src_stride_ar30,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1539 int AR30ToARGB(const uint8_t* src_ar30,
1540 int src_stride_ar30,
1541 uint8_t* dst_argb,
1542 int dst_stride_argb,
1543 int width,
1544 int height) {
1545 int y;
1546 if (!src_ar30 || !dst_argb || width <= 0 || height == 0) {
1547 return -1;
1548 }
1549 // Negative height means invert the image.
1550 if (height < 0) {
1551 height = -height;
1552 src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
1553 src_stride_ar30 = -src_stride_ar30;
1554 }
1555 // Coalesce rows.
1556 if (src_stride_ar30 == width * 4 && dst_stride_argb == width * 4) {
1557 width *= height;
1558 height = 1;
1559 src_stride_ar30 = dst_stride_argb = 0;
1560 }
1561 for (y = 0; y < height; ++y) {
1562 AR30ToARGBRow_C(src_ar30, dst_argb, width);
1563 src_ar30 += src_stride_ar30;
1564 dst_argb += dst_stride_argb;
1565 }
1566 return 0;
1567 }
1568
1569 // Convert AR30 to ABGR.
1570 LIBYUV_API
AR30ToABGR(const uint8_t * src_ar30,int src_stride_ar30,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)1571 int AR30ToABGR(const uint8_t* src_ar30,
1572 int src_stride_ar30,
1573 uint8_t* dst_abgr,
1574 int dst_stride_abgr,
1575 int width,
1576 int height) {
1577 int y;
1578 if (!src_ar30 || !dst_abgr || width <= 0 || height == 0) {
1579 return -1;
1580 }
1581 // Negative height means invert the image.
1582 if (height < 0) {
1583 height = -height;
1584 src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
1585 src_stride_ar30 = -src_stride_ar30;
1586 }
1587 // Coalesce rows.
1588 if (src_stride_ar30 == width * 4 && dst_stride_abgr == width * 4) {
1589 width *= height;
1590 height = 1;
1591 src_stride_ar30 = dst_stride_abgr = 0;
1592 }
1593 for (y = 0; y < height; ++y) {
1594 AR30ToABGRRow_C(src_ar30, dst_abgr, width);
1595 src_ar30 += src_stride_ar30;
1596 dst_abgr += dst_stride_abgr;
1597 }
1598 return 0;
1599 }
1600
1601 // Convert AR30 to AB30.
1602 LIBYUV_API
AR30ToAB30(const uint8_t * src_ar30,int src_stride_ar30,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)1603 int AR30ToAB30(const uint8_t* src_ar30,
1604 int src_stride_ar30,
1605 uint8_t* dst_ab30,
1606 int dst_stride_ab30,
1607 int width,
1608 int height) {
1609 int y;
1610 if (!src_ar30 || !dst_ab30 || width <= 0 || height == 0) {
1611 return -1;
1612 }
1613 // Negative height means invert the image.
1614 if (height < 0) {
1615 height = -height;
1616 src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
1617 src_stride_ar30 = -src_stride_ar30;
1618 }
1619 // Coalesce rows.
1620 if (src_stride_ar30 == width * 4 && dst_stride_ab30 == width * 4) {
1621 width *= height;
1622 height = 1;
1623 src_stride_ar30 = dst_stride_ab30 = 0;
1624 }
1625 for (y = 0; y < height; ++y) {
1626 AR30ToAB30Row_C(src_ar30, dst_ab30, width);
1627 src_ar30 += src_stride_ar30;
1628 dst_ab30 += dst_stride_ab30;
1629 }
1630 return 0;
1631 }
1632
1633 // Convert NV12 to ARGB with matrix
NV12ToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)1634 static int NV12ToARGBMatrix(const uint8_t* src_y,
1635 int src_stride_y,
1636 const uint8_t* src_uv,
1637 int src_stride_uv,
1638 uint8_t* dst_argb,
1639 int dst_stride_argb,
1640 const struct YuvConstants* yuvconstants,
1641 int width,
1642 int height) {
1643 int y;
1644 void (*NV12ToARGBRow)(
1645 const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
1646 const struct YuvConstants* yuvconstants, int width) = NV12ToARGBRow_C;
1647 if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
1648 return -1;
1649 }
1650 // Negative height means invert the image.
1651 if (height < 0) {
1652 height = -height;
1653 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1654 dst_stride_argb = -dst_stride_argb;
1655 }
1656 #if defined(HAS_NV12TOARGBROW_SSSE3)
1657 if (TestCpuFlag(kCpuHasSSSE3)) {
1658 NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
1659 if (IS_ALIGNED(width, 8)) {
1660 NV12ToARGBRow = NV12ToARGBRow_SSSE3;
1661 }
1662 }
1663 #endif
1664 #if defined(HAS_NV12TOARGBROW_AVX2)
1665 if (TestCpuFlag(kCpuHasAVX2)) {
1666 NV12ToARGBRow = NV12ToARGBRow_Any_AVX2;
1667 if (IS_ALIGNED(width, 16)) {
1668 NV12ToARGBRow = NV12ToARGBRow_AVX2;
1669 }
1670 }
1671 #endif
1672 #if defined(HAS_NV12TOARGBROW_NEON)
1673 if (TestCpuFlag(kCpuHasNEON)) {
1674 NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
1675 if (IS_ALIGNED(width, 8)) {
1676 NV12ToARGBRow = NV12ToARGBRow_NEON;
1677 }
1678 }
1679 #endif
1680 #if defined(HAS_NV12TOARGBROW_MSA)
1681 if (TestCpuFlag(kCpuHasMSA)) {
1682 NV12ToARGBRow = NV12ToARGBRow_Any_MSA;
1683 if (IS_ALIGNED(width, 8)) {
1684 NV12ToARGBRow = NV12ToARGBRow_MSA;
1685 }
1686 }
1687 #endif
1688
1689 for (y = 0; y < height; ++y) {
1690 NV12ToARGBRow(src_y, src_uv, dst_argb, yuvconstants, width);
1691 dst_argb += dst_stride_argb;
1692 src_y += src_stride_y;
1693 if (y & 1) {
1694 src_uv += src_stride_uv;
1695 }
1696 }
1697 return 0;
1698 }
1699
1700 // Convert NV21 to ARGB with matrix
NV21ToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_vu,int src_stride_vu,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)1701 static int NV21ToARGBMatrix(const uint8_t* src_y,
1702 int src_stride_y,
1703 const uint8_t* src_vu,
1704 int src_stride_vu,
1705 uint8_t* dst_argb,
1706 int dst_stride_argb,
1707 const struct YuvConstants* yuvconstants,
1708 int width,
1709 int height) {
1710 int y;
1711 void (*NV21ToARGBRow)(
1712 const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
1713 const struct YuvConstants* yuvconstants, int width) = NV21ToARGBRow_C;
1714 if (!src_y || !src_vu || !dst_argb || width <= 0 || height == 0) {
1715 return -1;
1716 }
1717 // Negative height means invert the image.
1718 if (height < 0) {
1719 height = -height;
1720 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1721 dst_stride_argb = -dst_stride_argb;
1722 }
1723 #if defined(HAS_NV21TOARGBROW_SSSE3)
1724 if (TestCpuFlag(kCpuHasSSSE3)) {
1725 NV21ToARGBRow = NV21ToARGBRow_Any_SSSE3;
1726 if (IS_ALIGNED(width, 8)) {
1727 NV21ToARGBRow = NV21ToARGBRow_SSSE3;
1728 }
1729 }
1730 #endif
1731 #if defined(HAS_NV21TOARGBROW_AVX2)
1732 if (TestCpuFlag(kCpuHasAVX2)) {
1733 NV21ToARGBRow = NV21ToARGBRow_Any_AVX2;
1734 if (IS_ALIGNED(width, 16)) {
1735 NV21ToARGBRow = NV21ToARGBRow_AVX2;
1736 }
1737 }
1738 #endif
1739 #if defined(HAS_NV21TOARGBROW_NEON)
1740 if (TestCpuFlag(kCpuHasNEON)) {
1741 NV21ToARGBRow = NV21ToARGBRow_Any_NEON;
1742 if (IS_ALIGNED(width, 8)) {
1743 NV21ToARGBRow = NV21ToARGBRow_NEON;
1744 }
1745 }
1746 #endif
1747 #if defined(HAS_NV21TOARGBROW_MSA)
1748 if (TestCpuFlag(kCpuHasMSA)) {
1749 NV21ToARGBRow = NV21ToARGBRow_Any_MSA;
1750 if (IS_ALIGNED(width, 8)) {
1751 NV21ToARGBRow = NV21ToARGBRow_MSA;
1752 }
1753 }
1754 #endif
1755
1756 for (y = 0; y < height; ++y) {
1757 NV21ToARGBRow(src_y, src_vu, dst_argb, yuvconstants, width);
1758 dst_argb += dst_stride_argb;
1759 src_y += src_stride_y;
1760 if (y & 1) {
1761 src_vu += src_stride_vu;
1762 }
1763 }
1764 return 0;
1765 }
1766
1767 // Convert NV12 to ARGB.
1768 LIBYUV_API
NV12ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1769 int NV12ToARGB(const uint8_t* src_y,
1770 int src_stride_y,
1771 const uint8_t* src_uv,
1772 int src_stride_uv,
1773 uint8_t* dst_argb,
1774 int dst_stride_argb,
1775 int width,
1776 int height) {
1777 return NV12ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_argb,
1778 dst_stride_argb, &kYuvI601Constants, width, height);
1779 }
1780
1781 // Convert NV21 to ARGB.
1782 LIBYUV_API
NV21ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_vu,int src_stride_vu,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1783 int NV21ToARGB(const uint8_t* src_y,
1784 int src_stride_y,
1785 const uint8_t* src_vu,
1786 int src_stride_vu,
1787 uint8_t* dst_argb,
1788 int dst_stride_argb,
1789 int width,
1790 int height) {
1791 return NV21ToARGBMatrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_argb,
1792 dst_stride_argb, &kYuvI601Constants, width, height);
1793 }
1794
1795 // Convert NV12 to ABGR.
1796 // To output ABGR instead of ARGB swap the UV and use a mirrored yuv matrix.
1797 // To swap the UV use NV12 instead of NV21.LIBYUV_API
1798 LIBYUV_API
NV12ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)1799 int NV12ToABGR(const uint8_t* src_y,
1800 int src_stride_y,
1801 const uint8_t* src_uv,
1802 int src_stride_uv,
1803 uint8_t* dst_abgr,
1804 int dst_stride_abgr,
1805 int width,
1806 int height) {
1807 return NV21ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_abgr,
1808 dst_stride_abgr, &kYvuI601Constants, width, height);
1809 }
1810
1811 // Convert NV21 to ABGR.
1812 LIBYUV_API
NV21ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_vu,int src_stride_vu,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)1813 int NV21ToABGR(const uint8_t* src_y,
1814 int src_stride_y,
1815 const uint8_t* src_vu,
1816 int src_stride_vu,
1817 uint8_t* dst_abgr,
1818 int dst_stride_abgr,
1819 int width,
1820 int height) {
1821 return NV12ToARGBMatrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_abgr,
1822 dst_stride_abgr, &kYvuI601Constants, width, height);
1823 }
1824
1825 // TODO(fbarchard): Consider SSSE3 2 step conversion.
1826 // Convert NV12 to RGB24 with matrix
NV12ToRGB24Matrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_rgb24,int dst_stride_rgb24,const struct YuvConstants * yuvconstants,int width,int height)1827 static int NV12ToRGB24Matrix(const uint8_t* src_y,
1828 int src_stride_y,
1829 const uint8_t* src_uv,
1830 int src_stride_uv,
1831 uint8_t* dst_rgb24,
1832 int dst_stride_rgb24,
1833 const struct YuvConstants* yuvconstants,
1834 int width,
1835 int height) {
1836 int y;
1837 void (*NV12ToRGB24Row)(
1838 const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
1839 const struct YuvConstants* yuvconstants, int width) = NV12ToRGB24Row_C;
1840 if (!src_y || !src_uv || !dst_rgb24 || width <= 0 || height == 0) {
1841 return -1;
1842 }
1843 // Negative height means invert the image.
1844 if (height < 0) {
1845 height = -height;
1846 dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
1847 dst_stride_rgb24 = -dst_stride_rgb24;
1848 }
1849 #if defined(HAS_NV12TORGB24ROW_NEON)
1850 if (TestCpuFlag(kCpuHasNEON)) {
1851 NV12ToRGB24Row = NV12ToRGB24Row_Any_NEON;
1852 if (IS_ALIGNED(width, 8)) {
1853 NV12ToRGB24Row = NV12ToRGB24Row_NEON;
1854 }
1855 }
1856 #endif
1857 #if defined(HAS_NV12TORGB24ROW_SSSE3)
1858 if (TestCpuFlag(kCpuHasSSSE3)) {
1859 NV12ToRGB24Row = NV12ToRGB24Row_Any_SSSE3;
1860 if (IS_ALIGNED(width, 16)) {
1861 NV12ToRGB24Row = NV12ToRGB24Row_SSSE3;
1862 }
1863 }
1864 #endif
1865 #if defined(HAS_NV12TORGB24ROW_AVX2)
1866 if (TestCpuFlag(kCpuHasAVX2)) {
1867 NV12ToRGB24Row = NV12ToRGB24Row_Any_AVX2;
1868 if (IS_ALIGNED(width, 32)) {
1869 NV12ToRGB24Row = NV12ToRGB24Row_AVX2;
1870 }
1871 }
1872 #endif
1873
1874 for (y = 0; y < height; ++y) {
1875 NV12ToRGB24Row(src_y, src_uv, dst_rgb24, yuvconstants, width);
1876 dst_rgb24 += dst_stride_rgb24;
1877 src_y += src_stride_y;
1878 if (y & 1) {
1879 src_uv += src_stride_uv;
1880 }
1881 }
1882 return 0;
1883 }
1884
1885 // Convert NV21 to RGB24 with matrix
NV21ToRGB24Matrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_vu,int src_stride_vu,uint8_t * dst_rgb24,int dst_stride_rgb24,const struct YuvConstants * yuvconstants,int width,int height)1886 static int NV21ToRGB24Matrix(const uint8_t* src_y,
1887 int src_stride_y,
1888 const uint8_t* src_vu,
1889 int src_stride_vu,
1890 uint8_t* dst_rgb24,
1891 int dst_stride_rgb24,
1892 const struct YuvConstants* yuvconstants,
1893 int width,
1894 int height) {
1895 int y;
1896 void (*NV21ToRGB24Row)(
1897 const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
1898 const struct YuvConstants* yuvconstants, int width) = NV21ToRGB24Row_C;
1899 if (!src_y || !src_vu || !dst_rgb24 || width <= 0 || height == 0) {
1900 return -1;
1901 }
1902 // Negative height means invert the image.
1903 if (height < 0) {
1904 height = -height;
1905 dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
1906 dst_stride_rgb24 = -dst_stride_rgb24;
1907 }
1908 #if defined(HAS_NV21TORGB24ROW_NEON)
1909 if (TestCpuFlag(kCpuHasNEON)) {
1910 NV21ToRGB24Row = NV21ToRGB24Row_Any_NEON;
1911 if (IS_ALIGNED(width, 8)) {
1912 NV21ToRGB24Row = NV21ToRGB24Row_NEON;
1913 }
1914 }
1915 #endif
1916 #if defined(HAS_NV21TORGB24ROW_SSSE3)
1917 if (TestCpuFlag(kCpuHasSSSE3)) {
1918 NV21ToRGB24Row = NV21ToRGB24Row_Any_SSSE3;
1919 if (IS_ALIGNED(width, 16)) {
1920 NV21ToRGB24Row = NV21ToRGB24Row_SSSE3;
1921 }
1922 }
1923 #endif
1924 #if defined(HAS_NV21TORGB24ROW_AVX2)
1925 if (TestCpuFlag(kCpuHasAVX2)) {
1926 NV21ToRGB24Row = NV21ToRGB24Row_Any_AVX2;
1927 if (IS_ALIGNED(width, 32)) {
1928 NV21ToRGB24Row = NV21ToRGB24Row_AVX2;
1929 }
1930 }
1931 #endif
1932
1933 for (y = 0; y < height; ++y) {
1934 NV21ToRGB24Row(src_y, src_vu, dst_rgb24, yuvconstants, width);
1935 dst_rgb24 += dst_stride_rgb24;
1936 src_y += src_stride_y;
1937 if (y & 1) {
1938 src_vu += src_stride_vu;
1939 }
1940 }
1941 return 0;
1942 }
1943
1944 // Convert NV12 to RGB24.
1945 LIBYUV_API
NV12ToRGB24(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_rgb24,int dst_stride_rgb24,int width,int height)1946 int NV12ToRGB24(const uint8_t* src_y,
1947 int src_stride_y,
1948 const uint8_t* src_uv,
1949 int src_stride_uv,
1950 uint8_t* dst_rgb24,
1951 int dst_stride_rgb24,
1952 int width,
1953 int height) {
1954 return NV12ToRGB24Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
1955 dst_rgb24, dst_stride_rgb24, &kYuvI601Constants,
1956 width, height);
1957 }
1958
1959 // Convert NV21 to RGB24.
1960 LIBYUV_API
NV21ToRGB24(const uint8_t * src_y,int src_stride_y,const uint8_t * src_vu,int src_stride_vu,uint8_t * dst_rgb24,int dst_stride_rgb24,int width,int height)1961 int NV21ToRGB24(const uint8_t* src_y,
1962 int src_stride_y,
1963 const uint8_t* src_vu,
1964 int src_stride_vu,
1965 uint8_t* dst_rgb24,
1966 int dst_stride_rgb24,
1967 int width,
1968 int height) {
1969 return NV21ToRGB24Matrix(src_y, src_stride_y, src_vu, src_stride_vu,
1970 dst_rgb24, dst_stride_rgb24, &kYuvI601Constants,
1971 width, height);
1972 }
1973
1974 // Convert NV12 to RAW.
1975 LIBYUV_API
NV12ToRAW(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_raw,int dst_stride_raw,int width,int height)1976 int NV12ToRAW(const uint8_t* src_y,
1977 int src_stride_y,
1978 const uint8_t* src_uv,
1979 int src_stride_uv,
1980 uint8_t* dst_raw,
1981 int dst_stride_raw,
1982 int width,
1983 int height) {
1984 return NV21ToRGB24Matrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_raw,
1985 dst_stride_raw, &kYvuI601Constants, width, height);
1986 }
1987
1988 // Convert NV21 to RAW.
1989 LIBYUV_API
NV21ToRAW(const uint8_t * src_y,int src_stride_y,const uint8_t * src_vu,int src_stride_vu,uint8_t * dst_raw,int dst_stride_raw,int width,int height)1990 int NV21ToRAW(const uint8_t* src_y,
1991 int src_stride_y,
1992 const uint8_t* src_vu,
1993 int src_stride_vu,
1994 uint8_t* dst_raw,
1995 int dst_stride_raw,
1996 int width,
1997 int height) {
1998 return NV12ToRGB24Matrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_raw,
1999 dst_stride_raw, &kYvuI601Constants, width, height);
2000 }
2001
2002 // Convert NV21 to YUV24
NV21ToYUV24(const uint8_t * src_y,int src_stride_y,const uint8_t * src_vu,int src_stride_vu,uint8_t * dst_yuv24,int dst_stride_yuv24,int width,int height)2003 int NV21ToYUV24(const uint8_t* src_y,
2004 int src_stride_y,
2005 const uint8_t* src_vu,
2006 int src_stride_vu,
2007 uint8_t* dst_yuv24,
2008 int dst_stride_yuv24,
2009 int width,
2010 int height) {
2011 int y;
2012 void (*NV21ToYUV24Row)(const uint8_t* src_y, const uint8_t* src_vu,
2013 uint8_t* dst_yuv24, int width) = NV21ToYUV24Row_C;
2014 if (!src_y || !src_vu || !dst_yuv24 || width <= 0 || height == 0) {
2015 return -1;
2016 }
2017 // Negative height means invert the image.
2018 if (height < 0) {
2019 height = -height;
2020 dst_yuv24 = dst_yuv24 + (height - 1) * dst_stride_yuv24;
2021 dst_stride_yuv24 = -dst_stride_yuv24;
2022 }
2023 #if defined(HAS_NV21TOYUV24ROW_NEON)
2024 if (TestCpuFlag(kCpuHasNEON)) {
2025 NV21ToYUV24Row = NV21ToYUV24Row_Any_NEON;
2026 if (IS_ALIGNED(width, 16)) {
2027 NV21ToYUV24Row = NV21ToYUV24Row_NEON;
2028 }
2029 }
2030 #endif
2031 #if defined(HAS_NV21TOYUV24ROW_AVX2)
2032 if (TestCpuFlag(kCpuHasAVX2)) {
2033 NV21ToYUV24Row = NV21ToYUV24Row_Any_AVX2;
2034 if (IS_ALIGNED(width, 32)) {
2035 NV21ToYUV24Row = NV21ToYUV24Row_AVX2;
2036 }
2037 }
2038 #endif
2039 for (y = 0; y < height; ++y) {
2040 NV21ToYUV24Row(src_y, src_vu, dst_yuv24, width);
2041 dst_yuv24 += dst_stride_yuv24;
2042 src_y += src_stride_y;
2043 if (y & 1) {
2044 src_vu += src_stride_vu;
2045 }
2046 }
2047 return 0;
2048 }
2049
2050 // Convert M420 to ARGB.
2051 LIBYUV_API
M420ToARGB(const uint8_t * src_m420,int src_stride_m420,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2052 int M420ToARGB(const uint8_t* src_m420,
2053 int src_stride_m420,
2054 uint8_t* dst_argb,
2055 int dst_stride_argb,
2056 int width,
2057 int height) {
2058 int y;
2059 void (*NV12ToARGBRow)(
2060 const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
2061 const struct YuvConstants* yuvconstants, int width) = NV12ToARGBRow_C;
2062 if (!src_m420 || !dst_argb || width <= 0 || height == 0) {
2063 return -1;
2064 }
2065 // Negative height means invert the image.
2066 if (height < 0) {
2067 height = -height;
2068 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2069 dst_stride_argb = -dst_stride_argb;
2070 }
2071 #if defined(HAS_NV12TOARGBROW_SSSE3)
2072 if (TestCpuFlag(kCpuHasSSSE3)) {
2073 NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
2074 if (IS_ALIGNED(width, 8)) {
2075 NV12ToARGBRow = NV12ToARGBRow_SSSE3;
2076 }
2077 }
2078 #endif
2079 #if defined(HAS_NV12TOARGBROW_AVX2)
2080 if (TestCpuFlag(kCpuHasAVX2)) {
2081 NV12ToARGBRow = NV12ToARGBRow_Any_AVX2;
2082 if (IS_ALIGNED(width, 16)) {
2083 NV12ToARGBRow = NV12ToARGBRow_AVX2;
2084 }
2085 }
2086 #endif
2087 #if defined(HAS_NV12TOARGBROW_NEON)
2088 if (TestCpuFlag(kCpuHasNEON)) {
2089 NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
2090 if (IS_ALIGNED(width, 8)) {
2091 NV12ToARGBRow = NV12ToARGBRow_NEON;
2092 }
2093 }
2094 #endif
2095 #if defined(HAS_NV12TOARGBROW_MSA)
2096 if (TestCpuFlag(kCpuHasMSA)) {
2097 NV12ToARGBRow = NV12ToARGBRow_Any_MSA;
2098 if (IS_ALIGNED(width, 8)) {
2099 NV12ToARGBRow = NV12ToARGBRow_MSA;
2100 }
2101 }
2102 #endif
2103
2104 for (y = 0; y < height - 1; y += 2) {
2105 NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb,
2106 &kYuvI601Constants, width);
2107 NV12ToARGBRow(src_m420 + src_stride_m420, src_m420 + src_stride_m420 * 2,
2108 dst_argb + dst_stride_argb, &kYuvI601Constants, width);
2109 dst_argb += dst_stride_argb * 2;
2110 src_m420 += src_stride_m420 * 3;
2111 }
2112 if (height & 1) {
2113 NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb,
2114 &kYuvI601Constants, width);
2115 }
2116 return 0;
2117 }
2118
2119 // Convert YUY2 to ARGB.
2120 LIBYUV_API
YUY2ToARGB(const uint8_t * src_yuy2,int src_stride_yuy2,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2121 int YUY2ToARGB(const uint8_t* src_yuy2,
2122 int src_stride_yuy2,
2123 uint8_t* dst_argb,
2124 int dst_stride_argb,
2125 int width,
2126 int height) {
2127 int y;
2128 void (*YUY2ToARGBRow)(const uint8_t* src_yuy2, uint8_t* dst_argb,
2129 const struct YuvConstants* yuvconstants, int width) =
2130 YUY2ToARGBRow_C;
2131 if (!src_yuy2 || !dst_argb || width <= 0 || height == 0) {
2132 return -1;
2133 }
2134 // Negative height means invert the image.
2135 if (height < 0) {
2136 height = -height;
2137 src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
2138 src_stride_yuy2 = -src_stride_yuy2;
2139 }
2140 // Coalesce rows.
2141 if (src_stride_yuy2 == width * 2 && dst_stride_argb == width * 4) {
2142 width *= height;
2143 height = 1;
2144 src_stride_yuy2 = dst_stride_argb = 0;
2145 }
2146 #if defined(HAS_YUY2TOARGBROW_SSSE3)
2147 if (TestCpuFlag(kCpuHasSSSE3)) {
2148 YUY2ToARGBRow = YUY2ToARGBRow_Any_SSSE3;
2149 if (IS_ALIGNED(width, 16)) {
2150 YUY2ToARGBRow = YUY2ToARGBRow_SSSE3;
2151 }
2152 }
2153 #endif
2154 #if defined(HAS_YUY2TOARGBROW_AVX2)
2155 if (TestCpuFlag(kCpuHasAVX2)) {
2156 YUY2ToARGBRow = YUY2ToARGBRow_Any_AVX2;
2157 if (IS_ALIGNED(width, 32)) {
2158 YUY2ToARGBRow = YUY2ToARGBRow_AVX2;
2159 }
2160 }
2161 #endif
2162 #if defined(HAS_YUY2TOARGBROW_NEON)
2163 if (TestCpuFlag(kCpuHasNEON)) {
2164 YUY2ToARGBRow = YUY2ToARGBRow_Any_NEON;
2165 if (IS_ALIGNED(width, 8)) {
2166 YUY2ToARGBRow = YUY2ToARGBRow_NEON;
2167 }
2168 }
2169 #endif
2170 #if defined(HAS_YUY2TOARGBROW_MSA)
2171 if (TestCpuFlag(kCpuHasMSA)) {
2172 YUY2ToARGBRow = YUY2ToARGBRow_Any_MSA;
2173 if (IS_ALIGNED(width, 8)) {
2174 YUY2ToARGBRow = YUY2ToARGBRow_MSA;
2175 }
2176 }
2177 #endif
2178 for (y = 0; y < height; ++y) {
2179 YUY2ToARGBRow(src_yuy2, dst_argb, &kYuvI601Constants, width);
2180 src_yuy2 += src_stride_yuy2;
2181 dst_argb += dst_stride_argb;
2182 }
2183 return 0;
2184 }
2185
2186 // Convert UYVY to ARGB.
2187 LIBYUV_API
UYVYToARGB(const uint8_t * src_uyvy,int src_stride_uyvy,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2188 int UYVYToARGB(const uint8_t* src_uyvy,
2189 int src_stride_uyvy,
2190 uint8_t* dst_argb,
2191 int dst_stride_argb,
2192 int width,
2193 int height) {
2194 int y;
2195 void (*UYVYToARGBRow)(const uint8_t* src_uyvy, uint8_t* dst_argb,
2196 const struct YuvConstants* yuvconstants, int width) =
2197 UYVYToARGBRow_C;
2198 if (!src_uyvy || !dst_argb || width <= 0 || height == 0) {
2199 return -1;
2200 }
2201 // Negative height means invert the image.
2202 if (height < 0) {
2203 height = -height;
2204 src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
2205 src_stride_uyvy = -src_stride_uyvy;
2206 }
2207 // Coalesce rows.
2208 if (src_stride_uyvy == width * 2 && dst_stride_argb == width * 4) {
2209 width *= height;
2210 height = 1;
2211 src_stride_uyvy = dst_stride_argb = 0;
2212 }
2213 #if defined(HAS_UYVYTOARGBROW_SSSE3)
2214 if (TestCpuFlag(kCpuHasSSSE3)) {
2215 UYVYToARGBRow = UYVYToARGBRow_Any_SSSE3;
2216 if (IS_ALIGNED(width, 16)) {
2217 UYVYToARGBRow = UYVYToARGBRow_SSSE3;
2218 }
2219 }
2220 #endif
2221 #if defined(HAS_UYVYTOARGBROW_AVX2)
2222 if (TestCpuFlag(kCpuHasAVX2)) {
2223 UYVYToARGBRow = UYVYToARGBRow_Any_AVX2;
2224 if (IS_ALIGNED(width, 32)) {
2225 UYVYToARGBRow = UYVYToARGBRow_AVX2;
2226 }
2227 }
2228 #endif
2229 #if defined(HAS_UYVYTOARGBROW_NEON)
2230 if (TestCpuFlag(kCpuHasNEON)) {
2231 UYVYToARGBRow = UYVYToARGBRow_Any_NEON;
2232 if (IS_ALIGNED(width, 8)) {
2233 UYVYToARGBRow = UYVYToARGBRow_NEON;
2234 }
2235 }
2236 #endif
2237 #if defined(HAS_UYVYTOARGBROW_MSA)
2238 if (TestCpuFlag(kCpuHasMSA)) {
2239 UYVYToARGBRow = UYVYToARGBRow_Any_MSA;
2240 if (IS_ALIGNED(width, 8)) {
2241 UYVYToARGBRow = UYVYToARGBRow_MSA;
2242 }
2243 }
2244 #endif
2245 for (y = 0; y < height; ++y) {
2246 UYVYToARGBRow(src_uyvy, dst_argb, &kYuvI601Constants, width);
2247 src_uyvy += src_stride_uyvy;
2248 dst_argb += dst_stride_argb;
2249 }
2250 return 0;
2251 }
WeavePixels(const uint8_t * src_u,const uint8_t * src_v,int src_pixel_stride_uv,uint8_t * dst_uv,int width)2252 static void WeavePixels(const uint8_t* src_u,
2253 const uint8_t* src_v,
2254 int src_pixel_stride_uv,
2255 uint8_t* dst_uv,
2256 int width) {
2257 int i;
2258 for (i = 0; i < width; ++i) {
2259 dst_uv[0] = *src_u;
2260 dst_uv[1] = *src_v;
2261 dst_uv += 2;
2262 src_u += src_pixel_stride_uv;
2263 src_v += src_pixel_stride_uv;
2264 }
2265 }
2266
2267 // Convert Android420 to ARGB.
2268 LIBYUV_API
Android420ToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,int src_pixel_stride_uv,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)2269 int Android420ToARGBMatrix(const uint8_t* src_y,
2270 int src_stride_y,
2271 const uint8_t* src_u,
2272 int src_stride_u,
2273 const uint8_t* src_v,
2274 int src_stride_v,
2275 int src_pixel_stride_uv,
2276 uint8_t* dst_argb,
2277 int dst_stride_argb,
2278 const struct YuvConstants* yuvconstants,
2279 int width,
2280 int height) {
2281 int y;
2282 uint8_t* dst_uv;
2283 const ptrdiff_t vu_off = src_v - src_u;
2284 int halfwidth = (width + 1) >> 1;
2285 int halfheight = (height + 1) >> 1;
2286 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
2287 return -1;
2288 }
2289 // Negative height means invert the image.
2290 if (height < 0) {
2291 height = -height;
2292 halfheight = (height + 1) >> 1;
2293 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2294 dst_stride_argb = -dst_stride_argb;
2295 }
2296
2297 // I420
2298 if (src_pixel_stride_uv == 1) {
2299 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
2300 src_stride_v, dst_argb, dst_stride_argb,
2301 yuvconstants, width, height);
2302 // NV21
2303 }
2304 if (src_pixel_stride_uv == 2 && vu_off == -1 &&
2305 src_stride_u == src_stride_v) {
2306 return NV21ToARGBMatrix(src_y, src_stride_y, src_v, src_stride_v, dst_argb,
2307 dst_stride_argb, yuvconstants, width, height);
2308 // NV12
2309 }
2310 if (src_pixel_stride_uv == 2 && vu_off == 1 && src_stride_u == src_stride_v) {
2311 return NV12ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, dst_argb,
2312 dst_stride_argb, yuvconstants, width, height);
2313 }
2314
2315 // General case fallback creates NV12
2316 align_buffer_64(plane_uv, halfwidth * 2 * halfheight);
2317 dst_uv = plane_uv;
2318 for (y = 0; y < halfheight; ++y) {
2319 WeavePixels(src_u, src_v, src_pixel_stride_uv, dst_uv, halfwidth);
2320 src_u += src_stride_u;
2321 src_v += src_stride_v;
2322 dst_uv += halfwidth * 2;
2323 }
2324 NV12ToARGBMatrix(src_y, src_stride_y, plane_uv, halfwidth * 2, dst_argb,
2325 dst_stride_argb, yuvconstants, width, height);
2326 free_aligned_buffer_64(plane_uv);
2327 return 0;
2328 }
2329
2330 // Convert Android420 to ARGB.
2331 LIBYUV_API
Android420ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,int src_pixel_stride_uv,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2332 int Android420ToARGB(const uint8_t* src_y,
2333 int src_stride_y,
2334 const uint8_t* src_u,
2335 int src_stride_u,
2336 const uint8_t* src_v,
2337 int src_stride_v,
2338 int src_pixel_stride_uv,
2339 uint8_t* dst_argb,
2340 int dst_stride_argb,
2341 int width,
2342 int height) {
2343 return Android420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
2344 src_stride_v, src_pixel_stride_uv, dst_argb,
2345 dst_stride_argb, &kYuvI601Constants, width,
2346 height);
2347 }
2348
2349 // Convert Android420 to ABGR.
2350 LIBYUV_API
Android420ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,int src_pixel_stride_uv,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)2351 int Android420ToABGR(const uint8_t* src_y,
2352 int src_stride_y,
2353 const uint8_t* src_u,
2354 int src_stride_u,
2355 const uint8_t* src_v,
2356 int src_stride_v,
2357 int src_pixel_stride_uv,
2358 uint8_t* dst_abgr,
2359 int dst_stride_abgr,
2360 int width,
2361 int height) {
2362 return Android420ToARGBMatrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
2363 src_stride_u, src_pixel_stride_uv, dst_abgr,
2364 dst_stride_abgr, &kYvuI601Constants, width,
2365 height);
2366 }
2367
2368 #ifdef __cplusplus
2369 } // extern "C"
2370 } // namespace libyuv
2371 #endif
2372