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