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 * src_argb,int src_stride_argb,uint8 * dst_argb,int dst_stride_argb,int width,int height)29 int ARGBCopy(const uint8* src_argb,
30 int src_stride_argb,
31 uint8* 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 I422 to ARGB with matrix
I420ToARGBMatrix(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,uint8 * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)51 static int I420ToARGBMatrix(const uint8* src_y,
52 int src_stride_y,
53 const uint8* src_u,
54 int src_stride_u,
55 const uint8* src_v,
56 int src_stride_v,
57 uint8* 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* y_buf, const uint8* u_buf,
64 const uint8* v_buf, uint8* 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_DSPR2)
101 if (TestCpuFlag(kCpuHasDSPR2) && IS_ALIGNED(width, 4) &&
102 IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
103 IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
104 IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
105 IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
106 I422ToARGBRow = I422ToARGBRow_DSPR2;
107 }
108 #endif
109 #if defined(HAS_I422TOARGBROW_MSA)
110 if (TestCpuFlag(kCpuHasMSA)) {
111 I422ToARGBRow = I422ToARGBRow_Any_MSA;
112 if (IS_ALIGNED(width, 8)) {
113 I422ToARGBRow = I422ToARGBRow_MSA;
114 }
115 }
116 #endif
117
118 for (y = 0; y < height; ++y) {
119 I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
120 dst_argb += dst_stride_argb;
121 src_y += src_stride_y;
122 if (y & 1) {
123 src_u += src_stride_u;
124 src_v += src_stride_v;
125 }
126 }
127 return 0;
128 }
129
130 // Convert I420 to ARGB.
131 LIBYUV_API
I420ToARGB(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,uint8 * dst_argb,int dst_stride_argb,int width,int height)132 int I420ToARGB(const uint8* src_y,
133 int src_stride_y,
134 const uint8* src_u,
135 int src_stride_u,
136 const uint8* src_v,
137 int src_stride_v,
138 uint8* dst_argb,
139 int dst_stride_argb,
140 int width,
141 int height) {
142 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
143 src_stride_v, dst_argb, dst_stride_argb,
144 &kYuvI601Constants, width, height);
145 }
146
147 // Convert I420 to ABGR.
148 LIBYUV_API
I420ToABGR(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,uint8 * dst_abgr,int dst_stride_abgr,int width,int height)149 int I420ToABGR(const uint8* src_y,
150 int src_stride_y,
151 const uint8* src_u,
152 int src_stride_u,
153 const uint8* src_v,
154 int src_stride_v,
155 uint8* dst_abgr,
156 int dst_stride_abgr,
157 int width,
158 int height) {
159 return I420ToARGBMatrix(src_y, src_stride_y, src_v,
160 src_stride_v, // Swap U and V
161 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
162 &kYvuI601Constants, // Use Yvu matrix
163 width, height);
164 }
165
166 // Convert J420 to ARGB.
167 LIBYUV_API
J420ToARGB(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,uint8 * dst_argb,int dst_stride_argb,int width,int height)168 int J420ToARGB(const uint8* src_y,
169 int src_stride_y,
170 const uint8* src_u,
171 int src_stride_u,
172 const uint8* src_v,
173 int src_stride_v,
174 uint8* dst_argb,
175 int dst_stride_argb,
176 int width,
177 int height) {
178 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
179 src_stride_v, dst_argb, dst_stride_argb,
180 &kYuvJPEGConstants, width, height);
181 }
182
183 // Convert J420 to ABGR.
184 LIBYUV_API
J420ToABGR(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,uint8 * dst_abgr,int dst_stride_abgr,int width,int height)185 int J420ToABGR(const uint8* src_y,
186 int src_stride_y,
187 const uint8* src_u,
188 int src_stride_u,
189 const uint8* src_v,
190 int src_stride_v,
191 uint8* dst_abgr,
192 int dst_stride_abgr,
193 int width,
194 int height) {
195 return I420ToARGBMatrix(src_y, src_stride_y, src_v,
196 src_stride_v, // Swap U and V
197 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
198 &kYvuJPEGConstants, // Use Yvu matrix
199 width, height);
200 }
201
202 // Convert H420 to ARGB.
203 LIBYUV_API
H420ToARGB(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,uint8 * dst_argb,int dst_stride_argb,int width,int height)204 int H420ToARGB(const uint8* src_y,
205 int src_stride_y,
206 const uint8* src_u,
207 int src_stride_u,
208 const uint8* src_v,
209 int src_stride_v,
210 uint8* dst_argb,
211 int dst_stride_argb,
212 int width,
213 int height) {
214 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
215 src_stride_v, dst_argb, dst_stride_argb,
216 &kYuvH709Constants, width, height);
217 }
218
219 // Convert H420 to ABGR.
220 LIBYUV_API
H420ToABGR(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,uint8 * dst_abgr,int dst_stride_abgr,int width,int height)221 int H420ToABGR(const uint8* src_y,
222 int src_stride_y,
223 const uint8* src_u,
224 int src_stride_u,
225 const uint8* src_v,
226 int src_stride_v,
227 uint8* dst_abgr,
228 int dst_stride_abgr,
229 int width,
230 int height) {
231 return I420ToARGBMatrix(src_y, src_stride_y, src_v,
232 src_stride_v, // Swap U and V
233 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
234 &kYvuH709Constants, // Use Yvu matrix
235 width, height);
236 }
237
238 // Convert I422 to ARGB with matrix
I422ToARGBMatrix(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,uint8 * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)239 static int I422ToARGBMatrix(const uint8* src_y,
240 int src_stride_y,
241 const uint8* src_u,
242 int src_stride_u,
243 const uint8* src_v,
244 int src_stride_v,
245 uint8* dst_argb,
246 int dst_stride_argb,
247 const struct YuvConstants* yuvconstants,
248 int width,
249 int height) {
250 int y;
251 void (*I422ToARGBRow)(const uint8* y_buf, const uint8* u_buf,
252 const uint8* v_buf, uint8* rgb_buf,
253 const struct YuvConstants* yuvconstants, int width) =
254 I422ToARGBRow_C;
255 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
256 return -1;
257 }
258 // Negative height means invert the image.
259 if (height < 0) {
260 height = -height;
261 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
262 dst_stride_argb = -dst_stride_argb;
263 }
264 // Coalesce rows.
265 if (src_stride_y == width && src_stride_u * 2 == width &&
266 src_stride_v * 2 == width && dst_stride_argb == width * 4) {
267 width *= height;
268 height = 1;
269 src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
270 }
271 #if defined(HAS_I422TOARGBROW_SSSE3)
272 if (TestCpuFlag(kCpuHasSSSE3)) {
273 I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
274 if (IS_ALIGNED(width, 8)) {
275 I422ToARGBRow = I422ToARGBRow_SSSE3;
276 }
277 }
278 #endif
279 #if defined(HAS_I422TOARGBROW_AVX2)
280 if (TestCpuFlag(kCpuHasAVX2)) {
281 I422ToARGBRow = I422ToARGBRow_Any_AVX2;
282 if (IS_ALIGNED(width, 16)) {
283 I422ToARGBRow = I422ToARGBRow_AVX2;
284 }
285 }
286 #endif
287 #if defined(HAS_I422TOARGBROW_NEON)
288 if (TestCpuFlag(kCpuHasNEON)) {
289 I422ToARGBRow = I422ToARGBRow_Any_NEON;
290 if (IS_ALIGNED(width, 8)) {
291 I422ToARGBRow = I422ToARGBRow_NEON;
292 }
293 }
294 #endif
295 #if defined(HAS_I422TOARGBROW_DSPR2)
296 if (TestCpuFlag(kCpuHasDSPR2) && IS_ALIGNED(width, 4) &&
297 IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
298 IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
299 IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
300 IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
301 I422ToARGBRow = I422ToARGBRow_DSPR2;
302 }
303 #endif
304 #if defined(HAS_I422TOARGBROW_MSA)
305 if (TestCpuFlag(kCpuHasMSA)) {
306 I422ToARGBRow = I422ToARGBRow_Any_MSA;
307 if (IS_ALIGNED(width, 8)) {
308 I422ToARGBRow = I422ToARGBRow_MSA;
309 }
310 }
311 #endif
312
313 for (y = 0; y < height; ++y) {
314 I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
315 dst_argb += dst_stride_argb;
316 src_y += src_stride_y;
317 src_u += src_stride_u;
318 src_v += src_stride_v;
319 }
320 return 0;
321 }
322
323 // Convert I422 to ARGB.
324 LIBYUV_API
I422ToARGB(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,uint8 * dst_argb,int dst_stride_argb,int width,int height)325 int I422ToARGB(const uint8* src_y,
326 int src_stride_y,
327 const uint8* src_u,
328 int src_stride_u,
329 const uint8* src_v,
330 int src_stride_v,
331 uint8* dst_argb,
332 int dst_stride_argb,
333 int width,
334 int height) {
335 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
336 src_stride_v, dst_argb, dst_stride_argb,
337 &kYuvI601Constants, width, height);
338 }
339
340 // Convert I422 to ABGR.
341 LIBYUV_API
I422ToABGR(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,uint8 * dst_abgr,int dst_stride_abgr,int width,int height)342 int I422ToABGR(const uint8* src_y,
343 int src_stride_y,
344 const uint8* src_u,
345 int src_stride_u,
346 const uint8* src_v,
347 int src_stride_v,
348 uint8* dst_abgr,
349 int dst_stride_abgr,
350 int width,
351 int height) {
352 return I422ToARGBMatrix(src_y, src_stride_y, src_v,
353 src_stride_v, // Swap U and V
354 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
355 &kYvuI601Constants, // Use Yvu matrix
356 width, height);
357 }
358
359 // Convert J422 to ARGB.
360 LIBYUV_API
J422ToARGB(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,uint8 * dst_argb,int dst_stride_argb,int width,int height)361 int J422ToARGB(const uint8* src_y,
362 int src_stride_y,
363 const uint8* src_u,
364 int src_stride_u,
365 const uint8* src_v,
366 int src_stride_v,
367 uint8* dst_argb,
368 int dst_stride_argb,
369 int width,
370 int height) {
371 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
372 src_stride_v, dst_argb, dst_stride_argb,
373 &kYuvJPEGConstants, width, height);
374 }
375
376 // Convert J422 to ABGR.
377 LIBYUV_API
J422ToABGR(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,uint8 * dst_abgr,int dst_stride_abgr,int width,int height)378 int J422ToABGR(const uint8* src_y,
379 int src_stride_y,
380 const uint8* src_u,
381 int src_stride_u,
382 const uint8* src_v,
383 int src_stride_v,
384 uint8* dst_abgr,
385 int dst_stride_abgr,
386 int width,
387 int height) {
388 return I422ToARGBMatrix(src_y, src_stride_y, src_v,
389 src_stride_v, // Swap U and V
390 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
391 &kYvuJPEGConstants, // Use Yvu matrix
392 width, height);
393 }
394
395 // Convert H422 to ARGB.
396 LIBYUV_API
H422ToARGB(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,uint8 * dst_argb,int dst_stride_argb,int width,int height)397 int H422ToARGB(const uint8* src_y,
398 int src_stride_y,
399 const uint8* src_u,
400 int src_stride_u,
401 const uint8* src_v,
402 int src_stride_v,
403 uint8* dst_argb,
404 int dst_stride_argb,
405 int width,
406 int height) {
407 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
408 src_stride_v, dst_argb, dst_stride_argb,
409 &kYuvH709Constants, width, height);
410 }
411
412 // Convert H422 to ABGR.
413 LIBYUV_API
H422ToABGR(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,uint8 * dst_abgr,int dst_stride_abgr,int width,int height)414 int H422ToABGR(const uint8* src_y,
415 int src_stride_y,
416 const uint8* src_u,
417 int src_stride_u,
418 const uint8* src_v,
419 int src_stride_v,
420 uint8* dst_abgr,
421 int dst_stride_abgr,
422 int width,
423 int height) {
424 return I422ToARGBMatrix(src_y, src_stride_y, src_v,
425 src_stride_v, // Swap U and V
426 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
427 &kYvuH709Constants, // Use Yvu matrix
428 width, height);
429 }
430
431 // Convert I444 to ARGB with matrix
I444ToARGBMatrix(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,uint8 * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)432 static int I444ToARGBMatrix(const uint8* src_y,
433 int src_stride_y,
434 const uint8* src_u,
435 int src_stride_u,
436 const uint8* src_v,
437 int src_stride_v,
438 uint8* dst_argb,
439 int dst_stride_argb,
440 const struct YuvConstants* yuvconstants,
441 int width,
442 int height) {
443 int y;
444 void (*I444ToARGBRow)(const uint8* y_buf, const uint8* u_buf,
445 const uint8* v_buf, uint8* rgb_buf,
446 const struct YuvConstants* yuvconstants, int width) =
447 I444ToARGBRow_C;
448 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
449 return -1;
450 }
451 // Negative height means invert the image.
452 if (height < 0) {
453 height = -height;
454 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
455 dst_stride_argb = -dst_stride_argb;
456 }
457 // Coalesce rows.
458 if (src_stride_y == width && src_stride_u == width && src_stride_v == width &&
459 dst_stride_argb == width * 4) {
460 width *= height;
461 height = 1;
462 src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
463 }
464 #if defined(HAS_I444TOARGBROW_SSSE3)
465 if (TestCpuFlag(kCpuHasSSSE3)) {
466 I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
467 if (IS_ALIGNED(width, 8)) {
468 I444ToARGBRow = I444ToARGBRow_SSSE3;
469 }
470 }
471 #endif
472 #if defined(HAS_I444TOARGBROW_AVX2)
473 if (TestCpuFlag(kCpuHasAVX2)) {
474 I444ToARGBRow = I444ToARGBRow_Any_AVX2;
475 if (IS_ALIGNED(width, 16)) {
476 I444ToARGBRow = I444ToARGBRow_AVX2;
477 }
478 }
479 #endif
480 #if defined(HAS_I444TOARGBROW_NEON)
481 if (TestCpuFlag(kCpuHasNEON)) {
482 I444ToARGBRow = I444ToARGBRow_Any_NEON;
483 if (IS_ALIGNED(width, 8)) {
484 I444ToARGBRow = I444ToARGBRow_NEON;
485 }
486 }
487 #endif
488 #if defined(HAS_I444TOARGBROW_DSPR2)
489 if (TestCpuFlag(kCpuHasDSPR2)) {
490 I444ToARGBRow = I444ToARGBRow_Any_DSPR2;
491 if (IS_ALIGNED(width, 8)) {
492 I444ToARGBRow = I444ToARGBRow_DSPR2;
493 }
494 }
495 #endif
496 #if defined(HAS_I444TOARGBROW_MSA)
497 if (TestCpuFlag(kCpuHasMSA)) {
498 I444ToARGBRow = I444ToARGBRow_Any_MSA;
499 if (IS_ALIGNED(width, 8)) {
500 I444ToARGBRow = I444ToARGBRow_MSA;
501 }
502 }
503 #endif
504
505 for (y = 0; y < height; ++y) {
506 I444ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
507 dst_argb += dst_stride_argb;
508 src_y += src_stride_y;
509 src_u += src_stride_u;
510 src_v += src_stride_v;
511 }
512 return 0;
513 }
514
515 // Convert I444 to ARGB.
516 LIBYUV_API
I444ToARGB(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,uint8 * dst_argb,int dst_stride_argb,int width,int height)517 int I444ToARGB(const uint8* src_y,
518 int src_stride_y,
519 const uint8* src_u,
520 int src_stride_u,
521 const uint8* src_v,
522 int src_stride_v,
523 uint8* dst_argb,
524 int dst_stride_argb,
525 int width,
526 int height) {
527 return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
528 src_stride_v, dst_argb, dst_stride_argb,
529 &kYuvI601Constants, width, height);
530 }
531
532 // Convert H444 to ARGB.
533 LIBYUV_API
H444ToARGB(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,uint8 * dst_argb,int dst_stride_argb,int width,int height)534 int H444ToARGB(const uint8* src_y,
535 int src_stride_y,
536 const uint8* src_u,
537 int src_stride_u,
538 const uint8* src_v,
539 int src_stride_v,
540 uint8* dst_argb,
541 int dst_stride_argb,
542 int width,
543 int height) {
544 return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
545 src_stride_v, dst_argb, dst_stride_argb,
546 &kYuvH709Constants, width, height);
547 }
548
549 // Convert I444 to ABGR.
550 LIBYUV_API
I444ToABGR(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,uint8 * dst_abgr,int dst_stride_abgr,int width,int height)551 int I444ToABGR(const uint8* src_y,
552 int src_stride_y,
553 const uint8* src_u,
554 int src_stride_u,
555 const uint8* src_v,
556 int src_stride_v,
557 uint8* dst_abgr,
558 int dst_stride_abgr,
559 int width,
560 int height) {
561 return I444ToARGBMatrix(src_y, src_stride_y, src_v,
562 src_stride_v, // Swap U and V
563 src_u, src_stride_u, dst_abgr, dst_stride_abgr,
564 &kYvuI601Constants, // Use Yvu matrix
565 width, height);
566 }
567
568 // Convert J444 to ARGB.
569 LIBYUV_API
J444ToARGB(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,uint8 * dst_argb,int dst_stride_argb,int width,int height)570 int J444ToARGB(const uint8* src_y,
571 int src_stride_y,
572 const uint8* src_u,
573 int src_stride_u,
574 const uint8* src_v,
575 int src_stride_v,
576 uint8* dst_argb,
577 int dst_stride_argb,
578 int width,
579 int height) {
580 return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
581 src_stride_v, dst_argb, dst_stride_argb,
582 &kYuvJPEGConstants, width, height);
583 }
584
585 // Convert I420 with Alpha to preattenuated ARGB.
I420AlphaToARGBMatrix(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,const uint8 * src_a,int src_stride_a,uint8 * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,int attenuate)586 static int I420AlphaToARGBMatrix(const uint8* src_y,
587 int src_stride_y,
588 const uint8* src_u,
589 int src_stride_u,
590 const uint8* src_v,
591 int src_stride_v,
592 const uint8* src_a,
593 int src_stride_a,
594 uint8* dst_argb,
595 int dst_stride_argb,
596 const struct YuvConstants* yuvconstants,
597 int width,
598 int height,
599 int attenuate) {
600 int y;
601 void (*I422AlphaToARGBRow)(const uint8* y_buf, const uint8* u_buf,
602 const uint8* v_buf, const uint8* a_buf,
603 uint8* dst_argb,
604 const struct YuvConstants* yuvconstants,
605 int width) = I422AlphaToARGBRow_C;
606 void (*ARGBAttenuateRow)(const uint8* src_argb, uint8* dst_argb, int width) =
607 ARGBAttenuateRow_C;
608 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
609 return -1;
610 }
611 // Negative height means invert the image.
612 if (height < 0) {
613 height = -height;
614 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
615 dst_stride_argb = -dst_stride_argb;
616 }
617 #if defined(HAS_I422ALPHATOARGBROW_SSSE3)
618 if (TestCpuFlag(kCpuHasSSSE3)) {
619 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_SSSE3;
620 if (IS_ALIGNED(width, 8)) {
621 I422AlphaToARGBRow = I422AlphaToARGBRow_SSSE3;
622 }
623 }
624 #endif
625 #if defined(HAS_I422ALPHATOARGBROW_AVX2)
626 if (TestCpuFlag(kCpuHasAVX2)) {
627 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_AVX2;
628 if (IS_ALIGNED(width, 16)) {
629 I422AlphaToARGBRow = I422AlphaToARGBRow_AVX2;
630 }
631 }
632 #endif
633 #if defined(HAS_I422ALPHATOARGBROW_NEON)
634 if (TestCpuFlag(kCpuHasNEON)) {
635 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_NEON;
636 if (IS_ALIGNED(width, 8)) {
637 I422AlphaToARGBRow = I422AlphaToARGBRow_NEON;
638 }
639 }
640 #endif
641 #if defined(HAS_I422ALPHATOARGBROW_DSPR2)
642 if (TestCpuFlag(kCpuHasDSPR2) && IS_ALIGNED(width, 4) &&
643 IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
644 IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
645 IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
646 IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
647 I422AlphaToARGBRow = I422AlphaToARGBRow_DSPR2;
648 }
649 #endif
650 #if defined(HAS_I422ALPHATOARGBROW_MSA)
651 if (TestCpuFlag(kCpuHasMSA)) {
652 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_MSA;
653 if (IS_ALIGNED(width, 8)) {
654 I422AlphaToARGBRow = I422AlphaToARGBRow_MSA;
655 }
656 }
657 #endif
658 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
659 if (TestCpuFlag(kCpuHasSSSE3)) {
660 ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
661 if (IS_ALIGNED(width, 4)) {
662 ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
663 }
664 }
665 #endif
666 #if defined(HAS_ARGBATTENUATEROW_AVX2)
667 if (TestCpuFlag(kCpuHasAVX2)) {
668 ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
669 if (IS_ALIGNED(width, 8)) {
670 ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
671 }
672 }
673 #endif
674 #if defined(HAS_ARGBATTENUATEROW_NEON)
675 if (TestCpuFlag(kCpuHasNEON)) {
676 ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
677 if (IS_ALIGNED(width, 8)) {
678 ARGBAttenuateRow = ARGBAttenuateRow_NEON;
679 }
680 }
681 #endif
682 #if defined(HAS_ARGBATTENUATEROW_MSA)
683 if (TestCpuFlag(kCpuHasMSA)) {
684 ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
685 if (IS_ALIGNED(width, 8)) {
686 ARGBAttenuateRow = ARGBAttenuateRow_MSA;
687 }
688 }
689 #endif
690
691 for (y = 0; y < height; ++y) {
692 I422AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
693 width);
694 if (attenuate) {
695 ARGBAttenuateRow(dst_argb, dst_argb, width);
696 }
697 dst_argb += dst_stride_argb;
698 src_a += src_stride_a;
699 src_y += src_stride_y;
700 if (y & 1) {
701 src_u += src_stride_u;
702 src_v += src_stride_v;
703 }
704 }
705 return 0;
706 }
707
708 // Convert I420 with Alpha to ARGB.
709 LIBYUV_API
I420AlphaToARGB(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,const uint8 * src_a,int src_stride_a,uint8 * dst_argb,int dst_stride_argb,int width,int height,int attenuate)710 int I420AlphaToARGB(const uint8* src_y,
711 int src_stride_y,
712 const uint8* src_u,
713 int src_stride_u,
714 const uint8* src_v,
715 int src_stride_v,
716 const uint8* src_a,
717 int src_stride_a,
718 uint8* dst_argb,
719 int dst_stride_argb,
720 int width,
721 int height,
722 int attenuate) {
723 return I420AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
724 src_stride_v, src_a, src_stride_a, dst_argb,
725 dst_stride_argb, &kYuvI601Constants, width,
726 height, attenuate);
727 }
728
729 // Convert I420 with Alpha to ABGR.
730 LIBYUV_API
I420AlphaToABGR(const uint8 * src_y,int src_stride_y,const uint8 * src_u,int src_stride_u,const uint8 * src_v,int src_stride_v,const uint8 * src_a,int src_stride_a,uint8 * dst_abgr,int dst_stride_abgr,int width,int height,int attenuate)731 int I420AlphaToABGR(const uint8* src_y,
732 int src_stride_y,
733 const uint8* src_u,
734 int src_stride_u,
735 const uint8* src_v,
736 int src_stride_v,
737 const uint8* src_a,
738 int src_stride_a,
739 uint8* dst_abgr,
740 int dst_stride_abgr,
741 int width,
742 int height,
743 int attenuate) {
744 return I420AlphaToARGBMatrix(
745 src_y, src_stride_y, src_v, src_stride_v, // Swap U and V
746 src_u, src_stride_u, src_a, src_stride_a, dst_abgr, dst_stride_abgr,
747 &kYvuI601Constants, // Use Yvu matrix
748 width, height, attenuate);
749 }
750
751 // Convert I400 to ARGB.
752 LIBYUV_API
I400ToARGB(const uint8 * src_y,int src_stride_y,uint8 * dst_argb,int dst_stride_argb,int width,int height)753 int I400ToARGB(const uint8* src_y,
754 int src_stride_y,
755 uint8* dst_argb,
756 int dst_stride_argb,
757 int width,
758 int height) {
759 int y;
760 void (*I400ToARGBRow)(const uint8* y_buf, uint8* rgb_buf, int width) =
761 I400ToARGBRow_C;
762 if (!src_y || !dst_argb || width <= 0 || height == 0) {
763 return -1;
764 }
765 // Negative height means invert the image.
766 if (height < 0) {
767 height = -height;
768 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
769 dst_stride_argb = -dst_stride_argb;
770 }
771 // Coalesce rows.
772 if (src_stride_y == width && dst_stride_argb == width * 4) {
773 width *= height;
774 height = 1;
775 src_stride_y = dst_stride_argb = 0;
776 }
777 #if defined(HAS_I400TOARGBROW_SSE2)
778 if (TestCpuFlag(kCpuHasSSE2)) {
779 I400ToARGBRow = I400ToARGBRow_Any_SSE2;
780 if (IS_ALIGNED(width, 8)) {
781 I400ToARGBRow = I400ToARGBRow_SSE2;
782 }
783 }
784 #endif
785 #if defined(HAS_I400TOARGBROW_AVX2)
786 if (TestCpuFlag(kCpuHasAVX2)) {
787 I400ToARGBRow = I400ToARGBRow_Any_AVX2;
788 if (IS_ALIGNED(width, 16)) {
789 I400ToARGBRow = I400ToARGBRow_AVX2;
790 }
791 }
792 #endif
793 #if defined(HAS_I400TOARGBROW_NEON)
794 if (TestCpuFlag(kCpuHasNEON)) {
795 I400ToARGBRow = I400ToARGBRow_Any_NEON;
796 if (IS_ALIGNED(width, 8)) {
797 I400ToARGBRow = I400ToARGBRow_NEON;
798 }
799 }
800 #endif
801 #if defined(HAS_I400TOARGBROW_MSA)
802 if (TestCpuFlag(kCpuHasMSA)) {
803 I400ToARGBRow = I400ToARGBRow_Any_MSA;
804 if (IS_ALIGNED(width, 16)) {
805 I400ToARGBRow = I400ToARGBRow_MSA;
806 }
807 }
808 #endif
809
810 for (y = 0; y < height; ++y) {
811 I400ToARGBRow(src_y, dst_argb, width);
812 dst_argb += dst_stride_argb;
813 src_y += src_stride_y;
814 }
815 return 0;
816 }
817
818 // Convert J400 to ARGB.
819 LIBYUV_API
J400ToARGB(const uint8 * src_y,int src_stride_y,uint8 * dst_argb,int dst_stride_argb,int width,int height)820 int J400ToARGB(const uint8* src_y,
821 int src_stride_y,
822 uint8* dst_argb,
823 int dst_stride_argb,
824 int width,
825 int height) {
826 int y;
827 void (*J400ToARGBRow)(const uint8* src_y, uint8* dst_argb, int width) =
828 J400ToARGBRow_C;
829 if (!src_y || !dst_argb || width <= 0 || height == 0) {
830 return -1;
831 }
832 // Negative height means invert the image.
833 if (height < 0) {
834 height = -height;
835 src_y = src_y + (height - 1) * src_stride_y;
836 src_stride_y = -src_stride_y;
837 }
838 // Coalesce rows.
839 if (src_stride_y == width && dst_stride_argb == width * 4) {
840 width *= height;
841 height = 1;
842 src_stride_y = dst_stride_argb = 0;
843 }
844 #if defined(HAS_J400TOARGBROW_SSE2)
845 if (TestCpuFlag(kCpuHasSSE2)) {
846 J400ToARGBRow = J400ToARGBRow_Any_SSE2;
847 if (IS_ALIGNED(width, 8)) {
848 J400ToARGBRow = J400ToARGBRow_SSE2;
849 }
850 }
851 #endif
852 #if defined(HAS_J400TOARGBROW_AVX2)
853 if (TestCpuFlag(kCpuHasAVX2)) {
854 J400ToARGBRow = J400ToARGBRow_Any_AVX2;
855 if (IS_ALIGNED(width, 16)) {
856 J400ToARGBRow = J400ToARGBRow_AVX2;
857 }
858 }
859 #endif
860 #if defined(HAS_J400TOARGBROW_NEON)
861 if (TestCpuFlag(kCpuHasNEON)) {
862 J400ToARGBRow = J400ToARGBRow_Any_NEON;
863 if (IS_ALIGNED(width, 8)) {
864 J400ToARGBRow = J400ToARGBRow_NEON;
865 }
866 }
867 #endif
868 #if defined(HAS_J400TOARGBROW_MSA)
869 if (TestCpuFlag(kCpuHasMSA)) {
870 J400ToARGBRow = J400ToARGBRow_Any_MSA;
871 if (IS_ALIGNED(width, 16)) {
872 J400ToARGBRow = J400ToARGBRow_MSA;
873 }
874 }
875 #endif
876 for (y = 0; y < height; ++y) {
877 J400ToARGBRow(src_y, dst_argb, width);
878 src_y += src_stride_y;
879 dst_argb += dst_stride_argb;
880 }
881 return 0;
882 }
883
884 // Shuffle table for converting BGRA to ARGB.
885 static uvec8 kShuffleMaskBGRAToARGB = {3u, 2u, 1u, 0u, 7u, 6u, 5u, 4u,
886 11u, 10u, 9u, 8u, 15u, 14u, 13u, 12u};
887
888 // Shuffle table for converting ABGR to ARGB.
889 static uvec8 kShuffleMaskABGRToARGB = {2u, 1u, 0u, 3u, 6u, 5u, 4u, 7u,
890 10u, 9u, 8u, 11u, 14u, 13u, 12u, 15u};
891
892 // Shuffle table for converting RGBA to ARGB.
893 static uvec8 kShuffleMaskRGBAToARGB = {1u, 2u, 3u, 0u, 5u, 6u, 7u, 4u,
894 9u, 10u, 11u, 8u, 13u, 14u, 15u, 12u};
895
896 // Convert BGRA to ARGB.
897 LIBYUV_API
BGRAToARGB(const uint8 * src_bgra,int src_stride_bgra,uint8 * dst_argb,int dst_stride_argb,int width,int height)898 int BGRAToARGB(const uint8* src_bgra,
899 int src_stride_bgra,
900 uint8* dst_argb,
901 int dst_stride_argb,
902 int width,
903 int height) {
904 return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb,
905 (const uint8*)(&kShuffleMaskBGRAToARGB), width, height);
906 }
907
908 // Convert ARGB to BGRA (same as BGRAToARGB).
909 LIBYUV_API
ARGBToBGRA(const uint8 * src_bgra,int src_stride_bgra,uint8 * dst_argb,int dst_stride_argb,int width,int height)910 int ARGBToBGRA(const uint8* src_bgra,
911 int src_stride_bgra,
912 uint8* dst_argb,
913 int dst_stride_argb,
914 int width,
915 int height) {
916 return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb,
917 (const uint8*)(&kShuffleMaskBGRAToARGB), width, height);
918 }
919
920 // Convert ABGR to ARGB.
921 LIBYUV_API
ABGRToARGB(const uint8 * src_abgr,int src_stride_abgr,uint8 * dst_argb,int dst_stride_argb,int width,int height)922 int ABGRToARGB(const uint8* src_abgr,
923 int src_stride_abgr,
924 uint8* dst_argb,
925 int dst_stride_argb,
926 int width,
927 int height) {
928 return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb,
929 (const uint8*)(&kShuffleMaskABGRToARGB), width, height);
930 }
931
932 // Convert ARGB to ABGR to (same as ABGRToARGB).
933 LIBYUV_API
ARGBToABGR(const uint8 * src_abgr,int src_stride_abgr,uint8 * dst_argb,int dst_stride_argb,int width,int height)934 int ARGBToABGR(const uint8* src_abgr,
935 int src_stride_abgr,
936 uint8* dst_argb,
937 int dst_stride_argb,
938 int width,
939 int height) {
940 return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb,
941 (const uint8*)(&kShuffleMaskABGRToARGB), width, height);
942 }
943
944 // Convert RGBA to ARGB.
945 LIBYUV_API
RGBAToARGB(const uint8 * src_rgba,int src_stride_rgba,uint8 * dst_argb,int dst_stride_argb,int width,int height)946 int RGBAToARGB(const uint8* src_rgba,
947 int src_stride_rgba,
948 uint8* dst_argb,
949 int dst_stride_argb,
950 int width,
951 int height) {
952 return ARGBShuffle(src_rgba, src_stride_rgba, dst_argb, dst_stride_argb,
953 (const uint8*)(&kShuffleMaskRGBAToARGB), width, height);
954 }
955
956 // Convert RGB24 to ARGB.
957 LIBYUV_API
RGB24ToARGB(const uint8 * src_rgb24,int src_stride_rgb24,uint8 * dst_argb,int dst_stride_argb,int width,int height)958 int RGB24ToARGB(const uint8* src_rgb24,
959 int src_stride_rgb24,
960 uint8* dst_argb,
961 int dst_stride_argb,
962 int width,
963 int height) {
964 int y;
965 void (*RGB24ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int width) =
966 RGB24ToARGBRow_C;
967 if (!src_rgb24 || !dst_argb || width <= 0 || height == 0) {
968 return -1;
969 }
970 // Negative height means invert the image.
971 if (height < 0) {
972 height = -height;
973 src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24;
974 src_stride_rgb24 = -src_stride_rgb24;
975 }
976 // Coalesce rows.
977 if (src_stride_rgb24 == width * 3 && dst_stride_argb == width * 4) {
978 width *= height;
979 height = 1;
980 src_stride_rgb24 = dst_stride_argb = 0;
981 }
982 #if defined(HAS_RGB24TOARGBROW_SSSE3)
983 if (TestCpuFlag(kCpuHasSSSE3)) {
984 RGB24ToARGBRow = RGB24ToARGBRow_Any_SSSE3;
985 if (IS_ALIGNED(width, 16)) {
986 RGB24ToARGBRow = RGB24ToARGBRow_SSSE3;
987 }
988 }
989 #endif
990 #if defined(HAS_RGB24TOARGBROW_NEON)
991 if (TestCpuFlag(kCpuHasNEON)) {
992 RGB24ToARGBRow = RGB24ToARGBRow_Any_NEON;
993 if (IS_ALIGNED(width, 8)) {
994 RGB24ToARGBRow = RGB24ToARGBRow_NEON;
995 }
996 }
997 #endif
998 #if defined(HAS_RGB24TOARGBROW_DSPR2)
999 if (TestCpuFlag(kCpuHasDSPR2)) {
1000 RGB24ToARGBRow = RGB24ToARGBRow_Any_DSPR2;
1001 if (IS_ALIGNED(width, 8)) {
1002 RGB24ToARGBRow = RGB24ToARGBRow_DSPR2;
1003 }
1004 }
1005 #endif
1006 #if defined(HAS_RGB24TOARGBROW_MSA)
1007 if (TestCpuFlag(kCpuHasMSA)) {
1008 RGB24ToARGBRow = RGB24ToARGBRow_Any_MSA;
1009 if (IS_ALIGNED(width, 16)) {
1010 RGB24ToARGBRow = RGB24ToARGBRow_MSA;
1011 }
1012 }
1013 #endif
1014
1015 for (y = 0; y < height; ++y) {
1016 RGB24ToARGBRow(src_rgb24, dst_argb, width);
1017 src_rgb24 += src_stride_rgb24;
1018 dst_argb += dst_stride_argb;
1019 }
1020 return 0;
1021 }
1022
1023 // Convert RAW to ARGB.
1024 LIBYUV_API
RAWToARGB(const uint8 * src_raw,int src_stride_raw,uint8 * dst_argb,int dst_stride_argb,int width,int height)1025 int RAWToARGB(const uint8* src_raw,
1026 int src_stride_raw,
1027 uint8* dst_argb,
1028 int dst_stride_argb,
1029 int width,
1030 int height) {
1031 int y;
1032 void (*RAWToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int width) =
1033 RAWToARGBRow_C;
1034 if (!src_raw || !dst_argb || width <= 0 || height == 0) {
1035 return -1;
1036 }
1037 // Negative height means invert the image.
1038 if (height < 0) {
1039 height = -height;
1040 src_raw = src_raw + (height - 1) * src_stride_raw;
1041 src_stride_raw = -src_stride_raw;
1042 }
1043 // Coalesce rows.
1044 if (src_stride_raw == width * 3 && dst_stride_argb == width * 4) {
1045 width *= height;
1046 height = 1;
1047 src_stride_raw = dst_stride_argb = 0;
1048 }
1049 #if defined(HAS_RAWTOARGBROW_SSSE3)
1050 if (TestCpuFlag(kCpuHasSSSE3)) {
1051 RAWToARGBRow = RAWToARGBRow_Any_SSSE3;
1052 if (IS_ALIGNED(width, 16)) {
1053 RAWToARGBRow = RAWToARGBRow_SSSE3;
1054 }
1055 }
1056 #endif
1057 #if defined(HAS_RAWTOARGBROW_NEON)
1058 if (TestCpuFlag(kCpuHasNEON)) {
1059 RAWToARGBRow = RAWToARGBRow_Any_NEON;
1060 if (IS_ALIGNED(width, 8)) {
1061 RAWToARGBRow = RAWToARGBRow_NEON;
1062 }
1063 }
1064 #endif
1065 #if defined(HAS_RAWTOARGBROW_DSPR2)
1066 if (TestCpuFlag(kCpuHasDSPR2)) {
1067 RAWToARGBRow = RAWToARGBRow_Any_DSPR2;
1068 if (IS_ALIGNED(width, 8)) {
1069 RAWToARGBRow = RAWToARGBRow_DSPR2;
1070 }
1071 }
1072 #endif
1073 #if defined(HAS_RAWTOARGBROW_MSA)
1074 if (TestCpuFlag(kCpuHasMSA)) {
1075 RAWToARGBRow = RAWToARGBRow_Any_MSA;
1076 if (IS_ALIGNED(width, 16)) {
1077 RAWToARGBRow = RAWToARGBRow_MSA;
1078 }
1079 }
1080 #endif
1081
1082 for (y = 0; y < height; ++y) {
1083 RAWToARGBRow(src_raw, dst_argb, width);
1084 src_raw += src_stride_raw;
1085 dst_argb += dst_stride_argb;
1086 }
1087 return 0;
1088 }
1089
1090 // Convert RGB565 to ARGB.
1091 LIBYUV_API
RGB565ToARGB(const uint8 * src_rgb565,int src_stride_rgb565,uint8 * dst_argb,int dst_stride_argb,int width,int height)1092 int RGB565ToARGB(const uint8* src_rgb565,
1093 int src_stride_rgb565,
1094 uint8* dst_argb,
1095 int dst_stride_argb,
1096 int width,
1097 int height) {
1098 int y;
1099 void (*RGB565ToARGBRow)(const uint8* src_rgb565, uint8* dst_argb, int width) =
1100 RGB565ToARGBRow_C;
1101 if (!src_rgb565 || !dst_argb || width <= 0 || height == 0) {
1102 return -1;
1103 }
1104 // Negative height means invert the image.
1105 if (height < 0) {
1106 height = -height;
1107 src_rgb565 = src_rgb565 + (height - 1) * src_stride_rgb565;
1108 src_stride_rgb565 = -src_stride_rgb565;
1109 }
1110 // Coalesce rows.
1111 if (src_stride_rgb565 == width * 2 && dst_stride_argb == width * 4) {
1112 width *= height;
1113 height = 1;
1114 src_stride_rgb565 = dst_stride_argb = 0;
1115 }
1116 #if defined(HAS_RGB565TOARGBROW_SSE2)
1117 if (TestCpuFlag(kCpuHasSSE2)) {
1118 RGB565ToARGBRow = RGB565ToARGBRow_Any_SSE2;
1119 if (IS_ALIGNED(width, 8)) {
1120 RGB565ToARGBRow = RGB565ToARGBRow_SSE2;
1121 }
1122 }
1123 #endif
1124 #if defined(HAS_RGB565TOARGBROW_AVX2)
1125 if (TestCpuFlag(kCpuHasAVX2)) {
1126 RGB565ToARGBRow = RGB565ToARGBRow_Any_AVX2;
1127 if (IS_ALIGNED(width, 16)) {
1128 RGB565ToARGBRow = RGB565ToARGBRow_AVX2;
1129 }
1130 }
1131 #endif
1132 #if defined(HAS_RGB565TOARGBROW_NEON)
1133 if (TestCpuFlag(kCpuHasNEON)) {
1134 RGB565ToARGBRow = RGB565ToARGBRow_Any_NEON;
1135 if (IS_ALIGNED(width, 8)) {
1136 RGB565ToARGBRow = RGB565ToARGBRow_NEON;
1137 }
1138 }
1139 #endif
1140 #if defined(HAS_RGB565TOARGBROW_DSPR2)
1141 if (TestCpuFlag(kCpuHasDSPR2)) {
1142 RGB565ToARGBRow = RGB565ToARGBRow_Any_DSPR2;
1143 if (IS_ALIGNED(width, 8)) {
1144 RGB565ToARGBRow = RGB565ToARGBRow_DSPR2;
1145 }
1146 }
1147 #endif
1148 #if defined(HAS_RGB565TOARGBROW_MSA)
1149 if (TestCpuFlag(kCpuHasMSA)) {
1150 RGB565ToARGBRow = RGB565ToARGBRow_Any_MSA;
1151 if (IS_ALIGNED(width, 16)) {
1152 RGB565ToARGBRow = RGB565ToARGBRow_MSA;
1153 }
1154 }
1155 #endif
1156
1157 for (y = 0; y < height; ++y) {
1158 RGB565ToARGBRow(src_rgb565, dst_argb, width);
1159 src_rgb565 += src_stride_rgb565;
1160 dst_argb += dst_stride_argb;
1161 }
1162 return 0;
1163 }
1164
1165 // Convert ARGB1555 to ARGB.
1166 LIBYUV_API
ARGB1555ToARGB(const uint8 * src_argb1555,int src_stride_argb1555,uint8 * dst_argb,int dst_stride_argb,int width,int height)1167 int ARGB1555ToARGB(const uint8* src_argb1555,
1168 int src_stride_argb1555,
1169 uint8* dst_argb,
1170 int dst_stride_argb,
1171 int width,
1172 int height) {
1173 int y;
1174 void (*ARGB1555ToARGBRow)(const uint8* src_argb1555, uint8* dst_argb,
1175 int width) = ARGB1555ToARGBRow_C;
1176 if (!src_argb1555 || !dst_argb || width <= 0 || height == 0) {
1177 return -1;
1178 }
1179 // Negative height means invert the image.
1180 if (height < 0) {
1181 height = -height;
1182 src_argb1555 = src_argb1555 + (height - 1) * src_stride_argb1555;
1183 src_stride_argb1555 = -src_stride_argb1555;
1184 }
1185 // Coalesce rows.
1186 if (src_stride_argb1555 == width * 2 && dst_stride_argb == width * 4) {
1187 width *= height;
1188 height = 1;
1189 src_stride_argb1555 = dst_stride_argb = 0;
1190 }
1191 #if defined(HAS_ARGB1555TOARGBROW_SSE2)
1192 if (TestCpuFlag(kCpuHasSSE2)) {
1193 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_SSE2;
1194 if (IS_ALIGNED(width, 8)) {
1195 ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2;
1196 }
1197 }
1198 #endif
1199 #if defined(HAS_ARGB1555TOARGBROW_AVX2)
1200 if (TestCpuFlag(kCpuHasAVX2)) {
1201 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_AVX2;
1202 if (IS_ALIGNED(width, 16)) {
1203 ARGB1555ToARGBRow = ARGB1555ToARGBRow_AVX2;
1204 }
1205 }
1206 #endif
1207 #if defined(HAS_ARGB1555TOARGBROW_NEON)
1208 if (TestCpuFlag(kCpuHasNEON)) {
1209 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_NEON;
1210 if (IS_ALIGNED(width, 8)) {
1211 ARGB1555ToARGBRow = ARGB1555ToARGBRow_NEON;
1212 }
1213 }
1214 #endif
1215 #if defined(HAS_ARGB1555TOARGBROW_DSPR2)
1216 if (TestCpuFlag(kCpuHasDSPR2)) {
1217 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_DSPR2;
1218 if (IS_ALIGNED(width, 4)) {
1219 ARGB1555ToARGBRow = ARGB1555ToARGBRow_DSPR2;
1220 }
1221 }
1222 #endif
1223 #if defined(HAS_ARGB1555TOARGBROW_MSA)
1224 if (TestCpuFlag(kCpuHasMSA)) {
1225 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_MSA;
1226 if (IS_ALIGNED(width, 16)) {
1227 ARGB1555ToARGBRow = ARGB1555ToARGBRow_MSA;
1228 }
1229 }
1230 #endif
1231
1232 for (y = 0; y < height; ++y) {
1233 ARGB1555ToARGBRow(src_argb1555, dst_argb, width);
1234 src_argb1555 += src_stride_argb1555;
1235 dst_argb += dst_stride_argb;
1236 }
1237 return 0;
1238 }
1239
1240 // Convert ARGB4444 to ARGB.
1241 LIBYUV_API
ARGB4444ToARGB(const uint8 * src_argb4444,int src_stride_argb4444,uint8 * dst_argb,int dst_stride_argb,int width,int height)1242 int ARGB4444ToARGB(const uint8* src_argb4444,
1243 int src_stride_argb4444,
1244 uint8* dst_argb,
1245 int dst_stride_argb,
1246 int width,
1247 int height) {
1248 int y;
1249 void (*ARGB4444ToARGBRow)(const uint8* src_argb4444, uint8* dst_argb,
1250 int width) = ARGB4444ToARGBRow_C;
1251 if (!src_argb4444 || !dst_argb || width <= 0 || height == 0) {
1252 return -1;
1253 }
1254 // Negative height means invert the image.
1255 if (height < 0) {
1256 height = -height;
1257 src_argb4444 = src_argb4444 + (height - 1) * src_stride_argb4444;
1258 src_stride_argb4444 = -src_stride_argb4444;
1259 }
1260 // Coalesce rows.
1261 if (src_stride_argb4444 == width * 2 && dst_stride_argb == width * 4) {
1262 width *= height;
1263 height = 1;
1264 src_stride_argb4444 = dst_stride_argb = 0;
1265 }
1266 #if defined(HAS_ARGB4444TOARGBROW_SSE2)
1267 if (TestCpuFlag(kCpuHasSSE2)) {
1268 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_SSE2;
1269 if (IS_ALIGNED(width, 8)) {
1270 ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2;
1271 }
1272 }
1273 #endif
1274 #if defined(HAS_ARGB4444TOARGBROW_AVX2)
1275 if (TestCpuFlag(kCpuHasAVX2)) {
1276 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_AVX2;
1277 if (IS_ALIGNED(width, 16)) {
1278 ARGB4444ToARGBRow = ARGB4444ToARGBRow_AVX2;
1279 }
1280 }
1281 #endif
1282 #if defined(HAS_ARGB4444TOARGBROW_NEON)
1283 if (TestCpuFlag(kCpuHasNEON)) {
1284 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_NEON;
1285 if (IS_ALIGNED(width, 8)) {
1286 ARGB4444ToARGBRow = ARGB4444ToARGBRow_NEON;
1287 }
1288 }
1289 #endif
1290 #if defined(HAS_ARGB4444TOARGBROW_DSPR2)
1291 if (TestCpuFlag(kCpuHasDSPR2)) {
1292 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_DSPR2;
1293 if (IS_ALIGNED(width, 4)) {
1294 ARGB4444ToARGBRow = ARGB4444ToARGBRow_DSPR2;
1295 }
1296 }
1297 #endif
1298 #if defined(HAS_ARGB4444TOARGBROW_MSA)
1299 if (TestCpuFlag(kCpuHasMSA)) {
1300 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_MSA;
1301 if (IS_ALIGNED(width, 16)) {
1302 ARGB4444ToARGBRow = ARGB4444ToARGBRow_MSA;
1303 }
1304 }
1305 #endif
1306
1307 for (y = 0; y < height; ++y) {
1308 ARGB4444ToARGBRow(src_argb4444, dst_argb, width);
1309 src_argb4444 += src_stride_argb4444;
1310 dst_argb += dst_stride_argb;
1311 }
1312 return 0;
1313 }
1314
1315 // Convert NV12 to ARGB.
1316 LIBYUV_API
NV12ToARGB(const uint8 * src_y,int src_stride_y,const uint8 * src_uv,int src_stride_uv,uint8 * dst_argb,int dst_stride_argb,int width,int height)1317 int NV12ToARGB(const uint8* src_y,
1318 int src_stride_y,
1319 const uint8* src_uv,
1320 int src_stride_uv,
1321 uint8* dst_argb,
1322 int dst_stride_argb,
1323 int width,
1324 int height) {
1325 int y;
1326 void (*NV12ToARGBRow)(const uint8* y_buf, const uint8* uv_buf, uint8* rgb_buf,
1327 const struct YuvConstants* yuvconstants, int width) =
1328 NV12ToARGBRow_C;
1329 if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
1330 return -1;
1331 }
1332 // Negative height means invert the image.
1333 if (height < 0) {
1334 height = -height;
1335 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1336 dst_stride_argb = -dst_stride_argb;
1337 }
1338 #if defined(HAS_NV12TOARGBROW_SSSE3)
1339 if (TestCpuFlag(kCpuHasSSSE3)) {
1340 NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
1341 if (IS_ALIGNED(width, 8)) {
1342 NV12ToARGBRow = NV12ToARGBRow_SSSE3;
1343 }
1344 }
1345 #endif
1346 #if defined(HAS_NV12TOARGBROW_AVX2)
1347 if (TestCpuFlag(kCpuHasAVX2)) {
1348 NV12ToARGBRow = NV12ToARGBRow_Any_AVX2;
1349 if (IS_ALIGNED(width, 16)) {
1350 NV12ToARGBRow = NV12ToARGBRow_AVX2;
1351 }
1352 }
1353 #endif
1354 #if defined(HAS_NV12TOARGBROW_NEON)
1355 if (TestCpuFlag(kCpuHasNEON)) {
1356 NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
1357 if (IS_ALIGNED(width, 8)) {
1358 NV12ToARGBRow = NV12ToARGBRow_NEON;
1359 }
1360 }
1361 #endif
1362 #if defined(HAS_NV12TOARGBROW_DSPR2)
1363 if (TestCpuFlag(kCpuHasDSPR2)) {
1364 NV12ToARGBRow = NV12ToARGBRow_Any_DSPR2;
1365 if (IS_ALIGNED(width, 8)) {
1366 NV12ToARGBRow = NV12ToARGBRow_DSPR2;
1367 }
1368 }
1369 #endif
1370 #if defined(HAS_NV12TOARGBROW_MSA)
1371 if (TestCpuFlag(kCpuHasMSA)) {
1372 NV12ToARGBRow = NV12ToARGBRow_Any_MSA;
1373 if (IS_ALIGNED(width, 8)) {
1374 NV12ToARGBRow = NV12ToARGBRow_MSA;
1375 }
1376 }
1377 #endif
1378
1379 for (y = 0; y < height; ++y) {
1380 NV12ToARGBRow(src_y, src_uv, dst_argb, &kYuvI601Constants, width);
1381 dst_argb += dst_stride_argb;
1382 src_y += src_stride_y;
1383 if (y & 1) {
1384 src_uv += src_stride_uv;
1385 }
1386 }
1387 return 0;
1388 }
1389
1390 // Convert NV21 to ARGB.
1391 LIBYUV_API
NV21ToARGB(const uint8 * src_y,int src_stride_y,const uint8 * src_uv,int src_stride_uv,uint8 * dst_argb,int dst_stride_argb,int width,int height)1392 int NV21ToARGB(const uint8* src_y,
1393 int src_stride_y,
1394 const uint8* src_uv,
1395 int src_stride_uv,
1396 uint8* dst_argb,
1397 int dst_stride_argb,
1398 int width,
1399 int height) {
1400 int y;
1401 void (*NV21ToARGBRow)(const uint8* y_buf, const uint8* uv_buf, uint8* rgb_buf,
1402 const struct YuvConstants* yuvconstants, int width) =
1403 NV21ToARGBRow_C;
1404 if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
1405 return -1;
1406 }
1407 // Negative height means invert the image.
1408 if (height < 0) {
1409 height = -height;
1410 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1411 dst_stride_argb = -dst_stride_argb;
1412 }
1413 #if defined(HAS_NV21TOARGBROW_SSSE3)
1414 if (TestCpuFlag(kCpuHasSSSE3)) {
1415 NV21ToARGBRow = NV21ToARGBRow_Any_SSSE3;
1416 if (IS_ALIGNED(width, 8)) {
1417 NV21ToARGBRow = NV21ToARGBRow_SSSE3;
1418 }
1419 }
1420 #endif
1421 #if defined(HAS_NV21TOARGBROW_AVX2)
1422 if (TestCpuFlag(kCpuHasAVX2)) {
1423 NV21ToARGBRow = NV21ToARGBRow_Any_AVX2;
1424 if (IS_ALIGNED(width, 16)) {
1425 NV21ToARGBRow = NV21ToARGBRow_AVX2;
1426 }
1427 }
1428 #endif
1429 #if defined(HAS_NV21TOARGBROW_NEON)
1430 if (TestCpuFlag(kCpuHasNEON)) {
1431 NV21ToARGBRow = NV21ToARGBRow_Any_NEON;
1432 if (IS_ALIGNED(width, 8)) {
1433 NV21ToARGBRow = NV21ToARGBRow_NEON;
1434 }
1435 }
1436 #endif
1437 #if defined(HAS_NV21TOARGBROW_MSA)
1438 if (TestCpuFlag(kCpuHasMSA)) {
1439 NV21ToARGBRow = NV21ToARGBRow_Any_MSA;
1440 if (IS_ALIGNED(width, 8)) {
1441 NV21ToARGBRow = NV21ToARGBRow_MSA;
1442 }
1443 }
1444 #endif
1445
1446 for (y = 0; y < height; ++y) {
1447 NV21ToARGBRow(src_y, src_uv, dst_argb, &kYuvI601Constants, width);
1448 dst_argb += dst_stride_argb;
1449 src_y += src_stride_y;
1450 if (y & 1) {
1451 src_uv += src_stride_uv;
1452 }
1453 }
1454 return 0;
1455 }
1456
1457 // Convert M420 to ARGB.
1458 LIBYUV_API
M420ToARGB(const uint8 * src_m420,int src_stride_m420,uint8 * dst_argb,int dst_stride_argb,int width,int height)1459 int M420ToARGB(const uint8* src_m420,
1460 int src_stride_m420,
1461 uint8* dst_argb,
1462 int dst_stride_argb,
1463 int width,
1464 int height) {
1465 int y;
1466 void (*NV12ToARGBRow)(const uint8* y_buf, const uint8* uv_buf, uint8* rgb_buf,
1467 const struct YuvConstants* yuvconstants, int width) =
1468 NV12ToARGBRow_C;
1469 if (!src_m420 || !dst_argb || width <= 0 || height == 0) {
1470 return -1;
1471 }
1472 // Negative height means invert the image.
1473 if (height < 0) {
1474 height = -height;
1475 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1476 dst_stride_argb = -dst_stride_argb;
1477 }
1478 #if defined(HAS_NV12TOARGBROW_SSSE3)
1479 if (TestCpuFlag(kCpuHasSSSE3)) {
1480 NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
1481 if (IS_ALIGNED(width, 8)) {
1482 NV12ToARGBRow = NV12ToARGBRow_SSSE3;
1483 }
1484 }
1485 #endif
1486 #if defined(HAS_NV12TOARGBROW_AVX2)
1487 if (TestCpuFlag(kCpuHasAVX2)) {
1488 NV12ToARGBRow = NV12ToARGBRow_Any_AVX2;
1489 if (IS_ALIGNED(width, 16)) {
1490 NV12ToARGBRow = NV12ToARGBRow_AVX2;
1491 }
1492 }
1493 #endif
1494 #if defined(HAS_NV12TOARGBROW_NEON)
1495 if (TestCpuFlag(kCpuHasNEON)) {
1496 NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
1497 if (IS_ALIGNED(width, 8)) {
1498 NV12ToARGBRow = NV12ToARGBRow_NEON;
1499 }
1500 }
1501 #endif
1502 #if defined(HAS_NV12TOARGBROW_DSPR2)
1503 if (TestCpuFlag(kCpuHasDSPR2)) {
1504 NV12ToARGBRow = NV12ToARGBRow_Any_DSPR2;
1505 if (IS_ALIGNED(width, 8)) {
1506 NV12ToARGBRow = NV12ToARGBRow_DSPR2;
1507 }
1508 }
1509 #endif
1510 #if defined(HAS_NV12TOARGBROW_MSA)
1511 if (TestCpuFlag(kCpuHasMSA)) {
1512 NV12ToARGBRow = NV12ToARGBRow_Any_MSA;
1513 if (IS_ALIGNED(width, 8)) {
1514 NV12ToARGBRow = NV12ToARGBRow_MSA;
1515 }
1516 }
1517 #endif
1518
1519 for (y = 0; y < height - 1; y += 2) {
1520 NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb,
1521 &kYuvI601Constants, width);
1522 NV12ToARGBRow(src_m420 + src_stride_m420, src_m420 + src_stride_m420 * 2,
1523 dst_argb + dst_stride_argb, &kYuvI601Constants, width);
1524 dst_argb += dst_stride_argb * 2;
1525 src_m420 += src_stride_m420 * 3;
1526 }
1527 if (height & 1) {
1528 NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb,
1529 &kYuvI601Constants, width);
1530 }
1531 return 0;
1532 }
1533
1534 // Convert YUY2 to ARGB.
1535 LIBYUV_API
YUY2ToARGB(const uint8 * src_yuy2,int src_stride_yuy2,uint8 * dst_argb,int dst_stride_argb,int width,int height)1536 int YUY2ToARGB(const uint8* src_yuy2,
1537 int src_stride_yuy2,
1538 uint8* dst_argb,
1539 int dst_stride_argb,
1540 int width,
1541 int height) {
1542 int y;
1543 void (*YUY2ToARGBRow)(const uint8* src_yuy2, uint8* dst_argb,
1544 const struct YuvConstants* yuvconstants, int width) =
1545 YUY2ToARGBRow_C;
1546 if (!src_yuy2 || !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_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
1553 src_stride_yuy2 = -src_stride_yuy2;
1554 }
1555 // Coalesce rows.
1556 if (src_stride_yuy2 == width * 2 && dst_stride_argb == width * 4) {
1557 width *= height;
1558 height = 1;
1559 src_stride_yuy2 = dst_stride_argb = 0;
1560 }
1561 #if defined(HAS_YUY2TOARGBROW_SSSE3)
1562 if (TestCpuFlag(kCpuHasSSSE3)) {
1563 YUY2ToARGBRow = YUY2ToARGBRow_Any_SSSE3;
1564 if (IS_ALIGNED(width, 16)) {
1565 YUY2ToARGBRow = YUY2ToARGBRow_SSSE3;
1566 }
1567 }
1568 #endif
1569 #if defined(HAS_YUY2TOARGBROW_AVX2)
1570 if (TestCpuFlag(kCpuHasAVX2)) {
1571 YUY2ToARGBRow = YUY2ToARGBRow_Any_AVX2;
1572 if (IS_ALIGNED(width, 32)) {
1573 YUY2ToARGBRow = YUY2ToARGBRow_AVX2;
1574 }
1575 }
1576 #endif
1577 #if defined(HAS_YUY2TOARGBROW_NEON)
1578 if (TestCpuFlag(kCpuHasNEON)) {
1579 YUY2ToARGBRow = YUY2ToARGBRow_Any_NEON;
1580 if (IS_ALIGNED(width, 8)) {
1581 YUY2ToARGBRow = YUY2ToARGBRow_NEON;
1582 }
1583 }
1584 #endif
1585 #if defined(HAS_YUY2TOARGBROW_MSA)
1586 if (TestCpuFlag(kCpuHasMSA)) {
1587 YUY2ToARGBRow = YUY2ToARGBRow_Any_MSA;
1588 if (IS_ALIGNED(width, 8)) {
1589 YUY2ToARGBRow = YUY2ToARGBRow_MSA;
1590 }
1591 }
1592 #endif
1593 for (y = 0; y < height; ++y) {
1594 YUY2ToARGBRow(src_yuy2, dst_argb, &kYuvI601Constants, width);
1595 src_yuy2 += src_stride_yuy2;
1596 dst_argb += dst_stride_argb;
1597 }
1598 return 0;
1599 }
1600
1601 // Convert UYVY to ARGB.
1602 LIBYUV_API
UYVYToARGB(const uint8 * src_uyvy,int src_stride_uyvy,uint8 * dst_argb,int dst_stride_argb,int width,int height)1603 int UYVYToARGB(const uint8* src_uyvy,
1604 int src_stride_uyvy,
1605 uint8* dst_argb,
1606 int dst_stride_argb,
1607 int width,
1608 int height) {
1609 int y;
1610 void (*UYVYToARGBRow)(const uint8* src_uyvy, uint8* dst_argb,
1611 const struct YuvConstants* yuvconstants, int width) =
1612 UYVYToARGBRow_C;
1613 if (!src_uyvy || !dst_argb || width <= 0 || height == 0) {
1614 return -1;
1615 }
1616 // Negative height means invert the image.
1617 if (height < 0) {
1618 height = -height;
1619 src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
1620 src_stride_uyvy = -src_stride_uyvy;
1621 }
1622 // Coalesce rows.
1623 if (src_stride_uyvy == width * 2 && dst_stride_argb == width * 4) {
1624 width *= height;
1625 height = 1;
1626 src_stride_uyvy = dst_stride_argb = 0;
1627 }
1628 #if defined(HAS_UYVYTOARGBROW_SSSE3)
1629 if (TestCpuFlag(kCpuHasSSSE3)) {
1630 UYVYToARGBRow = UYVYToARGBRow_Any_SSSE3;
1631 if (IS_ALIGNED(width, 16)) {
1632 UYVYToARGBRow = UYVYToARGBRow_SSSE3;
1633 }
1634 }
1635 #endif
1636 #if defined(HAS_UYVYTOARGBROW_AVX2)
1637 if (TestCpuFlag(kCpuHasAVX2)) {
1638 UYVYToARGBRow = UYVYToARGBRow_Any_AVX2;
1639 if (IS_ALIGNED(width, 32)) {
1640 UYVYToARGBRow = UYVYToARGBRow_AVX2;
1641 }
1642 }
1643 #endif
1644 #if defined(HAS_UYVYTOARGBROW_NEON)
1645 if (TestCpuFlag(kCpuHasNEON)) {
1646 UYVYToARGBRow = UYVYToARGBRow_Any_NEON;
1647 if (IS_ALIGNED(width, 8)) {
1648 UYVYToARGBRow = UYVYToARGBRow_NEON;
1649 }
1650 }
1651 #endif
1652 #if defined(HAS_UYVYTOARGBROW_MSA)
1653 if (TestCpuFlag(kCpuHasMSA)) {
1654 UYVYToARGBRow = UYVYToARGBRow_Any_MSA;
1655 if (IS_ALIGNED(width, 8)) {
1656 UYVYToARGBRow = UYVYToARGBRow_MSA;
1657 }
1658 }
1659 #endif
1660 for (y = 0; y < height; ++y) {
1661 UYVYToARGBRow(src_uyvy, dst_argb, &kYuvI601Constants, width);
1662 src_uyvy += src_stride_uyvy;
1663 dst_argb += dst_stride_argb;
1664 }
1665 return 0;
1666 }
1667
1668 #ifdef __cplusplus
1669 } // extern "C"
1670 } // namespace libyuv
1671 #endif
1672