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 I444 to ABGR.
533 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)534 int I444ToABGR(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_abgr,
541                int dst_stride_abgr,
542                int width,
543                int height) {
544   return I444ToARGBMatrix(src_y, src_stride_y, src_v,
545                           src_stride_v,  // Swap U and V
546                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
547                           &kYvuI601Constants,  // Use Yvu matrix
548                           width, height);
549 }
550 
551 // Convert J444 to ARGB.
552 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)553 int J444ToARGB(const uint8* src_y,
554                int src_stride_y,
555                const uint8* src_u,
556                int src_stride_u,
557                const uint8* src_v,
558                int src_stride_v,
559                uint8* dst_argb,
560                int dst_stride_argb,
561                int width,
562                int height) {
563   return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
564                           src_stride_v, dst_argb, dst_stride_argb,
565                           &kYuvJPEGConstants, width, height);
566 }
567 
568 // 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)569 static int I420AlphaToARGBMatrix(const uint8* src_y,
570                                  int src_stride_y,
571                                  const uint8* src_u,
572                                  int src_stride_u,
573                                  const uint8* src_v,
574                                  int src_stride_v,
575                                  const uint8* src_a,
576                                  int src_stride_a,
577                                  uint8* dst_argb,
578                                  int dst_stride_argb,
579                                  const struct YuvConstants* yuvconstants,
580                                  int width,
581                                  int height,
582                                  int attenuate) {
583   int y;
584   void (*I422AlphaToARGBRow)(const uint8* y_buf, const uint8* u_buf,
585                              const uint8* v_buf, const uint8* a_buf,
586                              uint8* dst_argb,
587                              const struct YuvConstants* yuvconstants,
588                              int width) = I422AlphaToARGBRow_C;
589   void (*ARGBAttenuateRow)(const uint8* src_argb, uint8* dst_argb, int width) =
590       ARGBAttenuateRow_C;
591   if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
592     return -1;
593   }
594   // Negative height means invert the image.
595   if (height < 0) {
596     height = -height;
597     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
598     dst_stride_argb = -dst_stride_argb;
599   }
600 #if defined(HAS_I422ALPHATOARGBROW_SSSE3)
601   if (TestCpuFlag(kCpuHasSSSE3)) {
602     I422AlphaToARGBRow = I422AlphaToARGBRow_Any_SSSE3;
603     if (IS_ALIGNED(width, 8)) {
604       I422AlphaToARGBRow = I422AlphaToARGBRow_SSSE3;
605     }
606   }
607 #endif
608 #if defined(HAS_I422ALPHATOARGBROW_AVX2)
609   if (TestCpuFlag(kCpuHasAVX2)) {
610     I422AlphaToARGBRow = I422AlphaToARGBRow_Any_AVX2;
611     if (IS_ALIGNED(width, 16)) {
612       I422AlphaToARGBRow = I422AlphaToARGBRow_AVX2;
613     }
614   }
615 #endif
616 #if defined(HAS_I422ALPHATOARGBROW_NEON)
617   if (TestCpuFlag(kCpuHasNEON)) {
618     I422AlphaToARGBRow = I422AlphaToARGBRow_Any_NEON;
619     if (IS_ALIGNED(width, 8)) {
620       I422AlphaToARGBRow = I422AlphaToARGBRow_NEON;
621     }
622   }
623 #endif
624 #if defined(HAS_I422ALPHATOARGBROW_DSPR2)
625   if (TestCpuFlag(kCpuHasDSPR2) && IS_ALIGNED(width, 4) &&
626       IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
627       IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
628       IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
629       IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
630     I422AlphaToARGBRow = I422AlphaToARGBRow_DSPR2;
631   }
632 #endif
633 #if defined(HAS_I422ALPHATOARGBROW_MSA)
634   if (TestCpuFlag(kCpuHasMSA)) {
635     I422AlphaToARGBRow = I422AlphaToARGBRow_Any_MSA;
636     if (IS_ALIGNED(width, 8)) {
637       I422AlphaToARGBRow = I422AlphaToARGBRow_MSA;
638     }
639   }
640 #endif
641 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
642   if (TestCpuFlag(kCpuHasSSSE3)) {
643     ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
644     if (IS_ALIGNED(width, 4)) {
645       ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
646     }
647   }
648 #endif
649 #if defined(HAS_ARGBATTENUATEROW_AVX2)
650   if (TestCpuFlag(kCpuHasAVX2)) {
651     ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
652     if (IS_ALIGNED(width, 8)) {
653       ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
654     }
655   }
656 #endif
657 #if defined(HAS_ARGBATTENUATEROW_NEON)
658   if (TestCpuFlag(kCpuHasNEON)) {
659     ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
660     if (IS_ALIGNED(width, 8)) {
661       ARGBAttenuateRow = ARGBAttenuateRow_NEON;
662     }
663   }
664 #endif
665 #if defined(HAS_ARGBATTENUATEROW_MSA)
666   if (TestCpuFlag(kCpuHasMSA)) {
667     ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
668     if (IS_ALIGNED(width, 8)) {
669       ARGBAttenuateRow = ARGBAttenuateRow_MSA;
670     }
671   }
672 #endif
673 
674   for (y = 0; y < height; ++y) {
675     I422AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
676                        width);
677     if (attenuate) {
678       ARGBAttenuateRow(dst_argb, dst_argb, width);
679     }
680     dst_argb += dst_stride_argb;
681     src_a += src_stride_a;
682     src_y += src_stride_y;
683     if (y & 1) {
684       src_u += src_stride_u;
685       src_v += src_stride_v;
686     }
687   }
688   return 0;
689 }
690 
691 // Convert I420 with Alpha to ARGB.
692 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)693 int I420AlphaToARGB(const uint8* src_y,
694                     int src_stride_y,
695                     const uint8* src_u,
696                     int src_stride_u,
697                     const uint8* src_v,
698                     int src_stride_v,
699                     const uint8* src_a,
700                     int src_stride_a,
701                     uint8* dst_argb,
702                     int dst_stride_argb,
703                     int width,
704                     int height,
705                     int attenuate) {
706   return I420AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
707                                src_stride_v, src_a, src_stride_a, dst_argb,
708                                dst_stride_argb, &kYuvI601Constants, width,
709                                height, attenuate);
710 }
711 
712 // Convert I420 with Alpha to ABGR.
713 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)714 int I420AlphaToABGR(const uint8* src_y,
715                     int src_stride_y,
716                     const uint8* src_u,
717                     int src_stride_u,
718                     const uint8* src_v,
719                     int src_stride_v,
720                     const uint8* src_a,
721                     int src_stride_a,
722                     uint8* dst_abgr,
723                     int dst_stride_abgr,
724                     int width,
725                     int height,
726                     int attenuate) {
727   return I420AlphaToARGBMatrix(
728       src_y, src_stride_y, src_v, src_stride_v,  // Swap U and V
729       src_u, src_stride_u, src_a, src_stride_a, dst_abgr, dst_stride_abgr,
730       &kYvuI601Constants,  // Use Yvu matrix
731       width, height, attenuate);
732 }
733 
734 // Convert I400 to ARGB.
735 LIBYUV_API
I400ToARGB(const uint8 * src_y,int src_stride_y,uint8 * dst_argb,int dst_stride_argb,int width,int height)736 int I400ToARGB(const uint8* src_y,
737                int src_stride_y,
738                uint8* dst_argb,
739                int dst_stride_argb,
740                int width,
741                int height) {
742   int y;
743   void (*I400ToARGBRow)(const uint8* y_buf, uint8* rgb_buf, int width) =
744       I400ToARGBRow_C;
745   if (!src_y || !dst_argb || width <= 0 || height == 0) {
746     return -1;
747   }
748   // Negative height means invert the image.
749   if (height < 0) {
750     height = -height;
751     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
752     dst_stride_argb = -dst_stride_argb;
753   }
754   // Coalesce rows.
755   if (src_stride_y == width && dst_stride_argb == width * 4) {
756     width *= height;
757     height = 1;
758     src_stride_y = dst_stride_argb = 0;
759   }
760 #if defined(HAS_I400TOARGBROW_SSE2)
761   if (TestCpuFlag(kCpuHasSSE2)) {
762     I400ToARGBRow = I400ToARGBRow_Any_SSE2;
763     if (IS_ALIGNED(width, 8)) {
764       I400ToARGBRow = I400ToARGBRow_SSE2;
765     }
766   }
767 #endif
768 #if defined(HAS_I400TOARGBROW_AVX2)
769   if (TestCpuFlag(kCpuHasAVX2)) {
770     I400ToARGBRow = I400ToARGBRow_Any_AVX2;
771     if (IS_ALIGNED(width, 16)) {
772       I400ToARGBRow = I400ToARGBRow_AVX2;
773     }
774   }
775 #endif
776 #if defined(HAS_I400TOARGBROW_NEON)
777   if (TestCpuFlag(kCpuHasNEON)) {
778     I400ToARGBRow = I400ToARGBRow_Any_NEON;
779     if (IS_ALIGNED(width, 8)) {
780       I400ToARGBRow = I400ToARGBRow_NEON;
781     }
782   }
783 #endif
784 #if defined(HAS_I400TOARGBROW_MSA)
785   if (TestCpuFlag(kCpuHasMSA)) {
786     I400ToARGBRow = I400ToARGBRow_Any_MSA;
787     if (IS_ALIGNED(width, 16)) {
788       I400ToARGBRow = I400ToARGBRow_MSA;
789     }
790   }
791 #endif
792 
793   for (y = 0; y < height; ++y) {
794     I400ToARGBRow(src_y, dst_argb, width);
795     dst_argb += dst_stride_argb;
796     src_y += src_stride_y;
797   }
798   return 0;
799 }
800 
801 // Convert J400 to ARGB.
802 LIBYUV_API
J400ToARGB(const uint8 * src_y,int src_stride_y,uint8 * dst_argb,int dst_stride_argb,int width,int height)803 int J400ToARGB(const uint8* src_y,
804                int src_stride_y,
805                uint8* dst_argb,
806                int dst_stride_argb,
807                int width,
808                int height) {
809   int y;
810   void (*J400ToARGBRow)(const uint8* src_y, uint8* dst_argb, int width) =
811       J400ToARGBRow_C;
812   if (!src_y || !dst_argb || width <= 0 || height == 0) {
813     return -1;
814   }
815   // Negative height means invert the image.
816   if (height < 0) {
817     height = -height;
818     src_y = src_y + (height - 1) * src_stride_y;
819     src_stride_y = -src_stride_y;
820   }
821   // Coalesce rows.
822   if (src_stride_y == width && dst_stride_argb == width * 4) {
823     width *= height;
824     height = 1;
825     src_stride_y = dst_stride_argb = 0;
826   }
827 #if defined(HAS_J400TOARGBROW_SSE2)
828   if (TestCpuFlag(kCpuHasSSE2)) {
829     J400ToARGBRow = J400ToARGBRow_Any_SSE2;
830     if (IS_ALIGNED(width, 8)) {
831       J400ToARGBRow = J400ToARGBRow_SSE2;
832     }
833   }
834 #endif
835 #if defined(HAS_J400TOARGBROW_AVX2)
836   if (TestCpuFlag(kCpuHasAVX2)) {
837     J400ToARGBRow = J400ToARGBRow_Any_AVX2;
838     if (IS_ALIGNED(width, 16)) {
839       J400ToARGBRow = J400ToARGBRow_AVX2;
840     }
841   }
842 #endif
843 #if defined(HAS_J400TOARGBROW_NEON)
844   if (TestCpuFlag(kCpuHasNEON)) {
845     J400ToARGBRow = J400ToARGBRow_Any_NEON;
846     if (IS_ALIGNED(width, 8)) {
847       J400ToARGBRow = J400ToARGBRow_NEON;
848     }
849   }
850 #endif
851 #if defined(HAS_J400TOARGBROW_MSA)
852   if (TestCpuFlag(kCpuHasMSA)) {
853     J400ToARGBRow = J400ToARGBRow_Any_MSA;
854     if (IS_ALIGNED(width, 16)) {
855       J400ToARGBRow = J400ToARGBRow_MSA;
856     }
857   }
858 #endif
859   for (y = 0; y < height; ++y) {
860     J400ToARGBRow(src_y, dst_argb, width);
861     src_y += src_stride_y;
862     dst_argb += dst_stride_argb;
863   }
864   return 0;
865 }
866 
867 // Shuffle table for converting BGRA to ARGB.
868 static uvec8 kShuffleMaskBGRAToARGB = {3u,  2u,  1u, 0u, 7u,  6u,  5u,  4u,
869                                        11u, 10u, 9u, 8u, 15u, 14u, 13u, 12u};
870 
871 // Shuffle table for converting ABGR to ARGB.
872 static uvec8 kShuffleMaskABGRToARGB = {2u,  1u, 0u, 3u,  6u,  5u,  4u,  7u,
873                                        10u, 9u, 8u, 11u, 14u, 13u, 12u, 15u};
874 
875 // Shuffle table for converting RGBA to ARGB.
876 static uvec8 kShuffleMaskRGBAToARGB = {1u, 2u,  3u,  0u, 5u,  6u,  7u,  4u,
877                                        9u, 10u, 11u, 8u, 13u, 14u, 15u, 12u};
878 
879 // Convert BGRA to ARGB.
880 LIBYUV_API
BGRAToARGB(const uint8 * src_bgra,int src_stride_bgra,uint8 * dst_argb,int dst_stride_argb,int width,int height)881 int BGRAToARGB(const uint8* src_bgra,
882                int src_stride_bgra,
883                uint8* dst_argb,
884                int dst_stride_argb,
885                int width,
886                int height) {
887   return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb,
888                      (const uint8*)(&kShuffleMaskBGRAToARGB), width, height);
889 }
890 
891 // Convert ARGB to BGRA (same as BGRAToARGB).
892 LIBYUV_API
ARGBToBGRA(const uint8 * src_bgra,int src_stride_bgra,uint8 * dst_argb,int dst_stride_argb,int width,int height)893 int ARGBToBGRA(const uint8* src_bgra,
894                int src_stride_bgra,
895                uint8* dst_argb,
896                int dst_stride_argb,
897                int width,
898                int height) {
899   return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb,
900                      (const uint8*)(&kShuffleMaskBGRAToARGB), width, height);
901 }
902 
903 // Convert ABGR to ARGB.
904 LIBYUV_API
ABGRToARGB(const uint8 * src_abgr,int src_stride_abgr,uint8 * dst_argb,int dst_stride_argb,int width,int height)905 int ABGRToARGB(const uint8* src_abgr,
906                int src_stride_abgr,
907                uint8* dst_argb,
908                int dst_stride_argb,
909                int width,
910                int height) {
911   return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb,
912                      (const uint8*)(&kShuffleMaskABGRToARGB), width, height);
913 }
914 
915 // Convert ARGB to ABGR to (same as ABGRToARGB).
916 LIBYUV_API
ARGBToABGR(const uint8 * src_abgr,int src_stride_abgr,uint8 * dst_argb,int dst_stride_argb,int width,int height)917 int ARGBToABGR(const uint8* src_abgr,
918                int src_stride_abgr,
919                uint8* dst_argb,
920                int dst_stride_argb,
921                int width,
922                int height) {
923   return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb,
924                      (const uint8*)(&kShuffleMaskABGRToARGB), width, height);
925 }
926 
927 // Convert RGBA to ARGB.
928 LIBYUV_API
RGBAToARGB(const uint8 * src_rgba,int src_stride_rgba,uint8 * dst_argb,int dst_stride_argb,int width,int height)929 int RGBAToARGB(const uint8* src_rgba,
930                int src_stride_rgba,
931                uint8* dst_argb,
932                int dst_stride_argb,
933                int width,
934                int height) {
935   return ARGBShuffle(src_rgba, src_stride_rgba, dst_argb, dst_stride_argb,
936                      (const uint8*)(&kShuffleMaskRGBAToARGB), width, height);
937 }
938 
939 // Convert RGB24 to ARGB.
940 LIBYUV_API
RGB24ToARGB(const uint8 * src_rgb24,int src_stride_rgb24,uint8 * dst_argb,int dst_stride_argb,int width,int height)941 int RGB24ToARGB(const uint8* src_rgb24,
942                 int src_stride_rgb24,
943                 uint8* dst_argb,
944                 int dst_stride_argb,
945                 int width,
946                 int height) {
947   int y;
948   void (*RGB24ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int width) =
949       RGB24ToARGBRow_C;
950   if (!src_rgb24 || !dst_argb || width <= 0 || height == 0) {
951     return -1;
952   }
953   // Negative height means invert the image.
954   if (height < 0) {
955     height = -height;
956     src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24;
957     src_stride_rgb24 = -src_stride_rgb24;
958   }
959   // Coalesce rows.
960   if (src_stride_rgb24 == width * 3 && dst_stride_argb == width * 4) {
961     width *= height;
962     height = 1;
963     src_stride_rgb24 = dst_stride_argb = 0;
964   }
965 #if defined(HAS_RGB24TOARGBROW_SSSE3)
966   if (TestCpuFlag(kCpuHasSSSE3)) {
967     RGB24ToARGBRow = RGB24ToARGBRow_Any_SSSE3;
968     if (IS_ALIGNED(width, 16)) {
969       RGB24ToARGBRow = RGB24ToARGBRow_SSSE3;
970     }
971   }
972 #endif
973 #if defined(HAS_RGB24TOARGBROW_NEON)
974   if (TestCpuFlag(kCpuHasNEON)) {
975     RGB24ToARGBRow = RGB24ToARGBRow_Any_NEON;
976     if (IS_ALIGNED(width, 8)) {
977       RGB24ToARGBRow = RGB24ToARGBRow_NEON;
978     }
979   }
980 #endif
981 #if defined(HAS_RGB24TOARGBROW_DSPR2)
982   if (TestCpuFlag(kCpuHasDSPR2)) {
983     RGB24ToARGBRow = RGB24ToARGBRow_Any_DSPR2;
984     if (IS_ALIGNED(width, 8)) {
985       RGB24ToARGBRow = RGB24ToARGBRow_DSPR2;
986     }
987   }
988 #endif
989 #if defined(HAS_RGB24TOARGBROW_MSA)
990   if (TestCpuFlag(kCpuHasMSA)) {
991     RGB24ToARGBRow = RGB24ToARGBRow_Any_MSA;
992     if (IS_ALIGNED(width, 16)) {
993       RGB24ToARGBRow = RGB24ToARGBRow_MSA;
994     }
995   }
996 #endif
997 
998   for (y = 0; y < height; ++y) {
999     RGB24ToARGBRow(src_rgb24, dst_argb, width);
1000     src_rgb24 += src_stride_rgb24;
1001     dst_argb += dst_stride_argb;
1002   }
1003   return 0;
1004 }
1005 
1006 // Convert RAW to ARGB.
1007 LIBYUV_API
RAWToARGB(const uint8 * src_raw,int src_stride_raw,uint8 * dst_argb,int dst_stride_argb,int width,int height)1008 int RAWToARGB(const uint8* src_raw,
1009               int src_stride_raw,
1010               uint8* dst_argb,
1011               int dst_stride_argb,
1012               int width,
1013               int height) {
1014   int y;
1015   void (*RAWToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int width) =
1016       RAWToARGBRow_C;
1017   if (!src_raw || !dst_argb || width <= 0 || height == 0) {
1018     return -1;
1019   }
1020   // Negative height means invert the image.
1021   if (height < 0) {
1022     height = -height;
1023     src_raw = src_raw + (height - 1) * src_stride_raw;
1024     src_stride_raw = -src_stride_raw;
1025   }
1026   // Coalesce rows.
1027   if (src_stride_raw == width * 3 && dst_stride_argb == width * 4) {
1028     width *= height;
1029     height = 1;
1030     src_stride_raw = dst_stride_argb = 0;
1031   }
1032 #if defined(HAS_RAWTOARGBROW_SSSE3)
1033   if (TestCpuFlag(kCpuHasSSSE3)) {
1034     RAWToARGBRow = RAWToARGBRow_Any_SSSE3;
1035     if (IS_ALIGNED(width, 16)) {
1036       RAWToARGBRow = RAWToARGBRow_SSSE3;
1037     }
1038   }
1039 #endif
1040 #if defined(HAS_RAWTOARGBROW_NEON)
1041   if (TestCpuFlag(kCpuHasNEON)) {
1042     RAWToARGBRow = RAWToARGBRow_Any_NEON;
1043     if (IS_ALIGNED(width, 8)) {
1044       RAWToARGBRow = RAWToARGBRow_NEON;
1045     }
1046   }
1047 #endif
1048 #if defined(HAS_RAWTOARGBROW_DSPR2)
1049   if (TestCpuFlag(kCpuHasDSPR2)) {
1050     RAWToARGBRow = RAWToARGBRow_Any_DSPR2;
1051     if (IS_ALIGNED(width, 8)) {
1052       RAWToARGBRow = RAWToARGBRow_DSPR2;
1053     }
1054   }
1055 #endif
1056 #if defined(HAS_RAWTOARGBROW_MSA)
1057   if (TestCpuFlag(kCpuHasMSA)) {
1058     RAWToARGBRow = RAWToARGBRow_Any_MSA;
1059     if (IS_ALIGNED(width, 16)) {
1060       RAWToARGBRow = RAWToARGBRow_MSA;
1061     }
1062   }
1063 #endif
1064 
1065   for (y = 0; y < height; ++y) {
1066     RAWToARGBRow(src_raw, dst_argb, width);
1067     src_raw += src_stride_raw;
1068     dst_argb += dst_stride_argb;
1069   }
1070   return 0;
1071 }
1072 
1073 // Convert RGB565 to ARGB.
1074 LIBYUV_API
RGB565ToARGB(const uint8 * src_rgb565,int src_stride_rgb565,uint8 * dst_argb,int dst_stride_argb,int width,int height)1075 int RGB565ToARGB(const uint8* src_rgb565,
1076                  int src_stride_rgb565,
1077                  uint8* dst_argb,
1078                  int dst_stride_argb,
1079                  int width,
1080                  int height) {
1081   int y;
1082   void (*RGB565ToARGBRow)(const uint8* src_rgb565, uint8* dst_argb, int width) =
1083       RGB565ToARGBRow_C;
1084   if (!src_rgb565 || !dst_argb || width <= 0 || height == 0) {
1085     return -1;
1086   }
1087   // Negative height means invert the image.
1088   if (height < 0) {
1089     height = -height;
1090     src_rgb565 = src_rgb565 + (height - 1) * src_stride_rgb565;
1091     src_stride_rgb565 = -src_stride_rgb565;
1092   }
1093   // Coalesce rows.
1094   if (src_stride_rgb565 == width * 2 && dst_stride_argb == width * 4) {
1095     width *= height;
1096     height = 1;
1097     src_stride_rgb565 = dst_stride_argb = 0;
1098   }
1099 #if defined(HAS_RGB565TOARGBROW_SSE2)
1100   if (TestCpuFlag(kCpuHasSSE2)) {
1101     RGB565ToARGBRow = RGB565ToARGBRow_Any_SSE2;
1102     if (IS_ALIGNED(width, 8)) {
1103       RGB565ToARGBRow = RGB565ToARGBRow_SSE2;
1104     }
1105   }
1106 #endif
1107 #if defined(HAS_RGB565TOARGBROW_AVX2)
1108   if (TestCpuFlag(kCpuHasAVX2)) {
1109     RGB565ToARGBRow = RGB565ToARGBRow_Any_AVX2;
1110     if (IS_ALIGNED(width, 16)) {
1111       RGB565ToARGBRow = RGB565ToARGBRow_AVX2;
1112     }
1113   }
1114 #endif
1115 #if defined(HAS_RGB565TOARGBROW_NEON)
1116   if (TestCpuFlag(kCpuHasNEON)) {
1117     RGB565ToARGBRow = RGB565ToARGBRow_Any_NEON;
1118     if (IS_ALIGNED(width, 8)) {
1119       RGB565ToARGBRow = RGB565ToARGBRow_NEON;
1120     }
1121   }
1122 #endif
1123 #if defined(HAS_RGB565TOARGBROW_DSPR2)
1124   if (TestCpuFlag(kCpuHasDSPR2)) {
1125     RGB565ToARGBRow = RGB565ToARGBRow_Any_DSPR2;
1126     if (IS_ALIGNED(width, 8)) {
1127       RGB565ToARGBRow = RGB565ToARGBRow_DSPR2;
1128     }
1129   }
1130 #endif
1131 #if defined(HAS_RGB565TOARGBROW_MSA)
1132   if (TestCpuFlag(kCpuHasMSA)) {
1133     RGB565ToARGBRow = RGB565ToARGBRow_Any_MSA;
1134     if (IS_ALIGNED(width, 16)) {
1135       RGB565ToARGBRow = RGB565ToARGBRow_MSA;
1136     }
1137   }
1138 #endif
1139 
1140   for (y = 0; y < height; ++y) {
1141     RGB565ToARGBRow(src_rgb565, dst_argb, width);
1142     src_rgb565 += src_stride_rgb565;
1143     dst_argb += dst_stride_argb;
1144   }
1145   return 0;
1146 }
1147 
1148 // Convert ARGB1555 to ARGB.
1149 LIBYUV_API
ARGB1555ToARGB(const uint8 * src_argb1555,int src_stride_argb1555,uint8 * dst_argb,int dst_stride_argb,int width,int height)1150 int ARGB1555ToARGB(const uint8* src_argb1555,
1151                    int src_stride_argb1555,
1152                    uint8* dst_argb,
1153                    int dst_stride_argb,
1154                    int width,
1155                    int height) {
1156   int y;
1157   void (*ARGB1555ToARGBRow)(const uint8* src_argb1555, uint8* dst_argb,
1158                             int width) = ARGB1555ToARGBRow_C;
1159   if (!src_argb1555 || !dst_argb || width <= 0 || height == 0) {
1160     return -1;
1161   }
1162   // Negative height means invert the image.
1163   if (height < 0) {
1164     height = -height;
1165     src_argb1555 = src_argb1555 + (height - 1) * src_stride_argb1555;
1166     src_stride_argb1555 = -src_stride_argb1555;
1167   }
1168   // Coalesce rows.
1169   if (src_stride_argb1555 == width * 2 && dst_stride_argb == width * 4) {
1170     width *= height;
1171     height = 1;
1172     src_stride_argb1555 = dst_stride_argb = 0;
1173   }
1174 #if defined(HAS_ARGB1555TOARGBROW_SSE2)
1175   if (TestCpuFlag(kCpuHasSSE2)) {
1176     ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_SSE2;
1177     if (IS_ALIGNED(width, 8)) {
1178       ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2;
1179     }
1180   }
1181 #endif
1182 #if defined(HAS_ARGB1555TOARGBROW_AVX2)
1183   if (TestCpuFlag(kCpuHasAVX2)) {
1184     ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_AVX2;
1185     if (IS_ALIGNED(width, 16)) {
1186       ARGB1555ToARGBRow = ARGB1555ToARGBRow_AVX2;
1187     }
1188   }
1189 #endif
1190 #if defined(HAS_ARGB1555TOARGBROW_NEON)
1191   if (TestCpuFlag(kCpuHasNEON)) {
1192     ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_NEON;
1193     if (IS_ALIGNED(width, 8)) {
1194       ARGB1555ToARGBRow = ARGB1555ToARGBRow_NEON;
1195     }
1196   }
1197 #endif
1198 #if defined(HAS_ARGB1555TOARGBROW_DSPR2)
1199   if (TestCpuFlag(kCpuHasDSPR2)) {
1200     ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_DSPR2;
1201     if (IS_ALIGNED(width, 4)) {
1202       ARGB1555ToARGBRow = ARGB1555ToARGBRow_DSPR2;
1203     }
1204   }
1205 #endif
1206 #if defined(HAS_ARGB1555TOARGBROW_MSA)
1207   if (TestCpuFlag(kCpuHasMSA)) {
1208     ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_MSA;
1209     if (IS_ALIGNED(width, 16)) {
1210       ARGB1555ToARGBRow = ARGB1555ToARGBRow_MSA;
1211     }
1212   }
1213 #endif
1214 
1215   for (y = 0; y < height; ++y) {
1216     ARGB1555ToARGBRow(src_argb1555, dst_argb, width);
1217     src_argb1555 += src_stride_argb1555;
1218     dst_argb += dst_stride_argb;
1219   }
1220   return 0;
1221 }
1222 
1223 // Convert ARGB4444 to ARGB.
1224 LIBYUV_API
ARGB4444ToARGB(const uint8 * src_argb4444,int src_stride_argb4444,uint8 * dst_argb,int dst_stride_argb,int width,int height)1225 int ARGB4444ToARGB(const uint8* src_argb4444,
1226                    int src_stride_argb4444,
1227                    uint8* dst_argb,
1228                    int dst_stride_argb,
1229                    int width,
1230                    int height) {
1231   int y;
1232   void (*ARGB4444ToARGBRow)(const uint8* src_argb4444, uint8* dst_argb,
1233                             int width) = ARGB4444ToARGBRow_C;
1234   if (!src_argb4444 || !dst_argb || width <= 0 || height == 0) {
1235     return -1;
1236   }
1237   // Negative height means invert the image.
1238   if (height < 0) {
1239     height = -height;
1240     src_argb4444 = src_argb4444 + (height - 1) * src_stride_argb4444;
1241     src_stride_argb4444 = -src_stride_argb4444;
1242   }
1243   // Coalesce rows.
1244   if (src_stride_argb4444 == width * 2 && dst_stride_argb == width * 4) {
1245     width *= height;
1246     height = 1;
1247     src_stride_argb4444 = dst_stride_argb = 0;
1248   }
1249 #if defined(HAS_ARGB4444TOARGBROW_SSE2)
1250   if (TestCpuFlag(kCpuHasSSE2)) {
1251     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_SSE2;
1252     if (IS_ALIGNED(width, 8)) {
1253       ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2;
1254     }
1255   }
1256 #endif
1257 #if defined(HAS_ARGB4444TOARGBROW_AVX2)
1258   if (TestCpuFlag(kCpuHasAVX2)) {
1259     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_AVX2;
1260     if (IS_ALIGNED(width, 16)) {
1261       ARGB4444ToARGBRow = ARGB4444ToARGBRow_AVX2;
1262     }
1263   }
1264 #endif
1265 #if defined(HAS_ARGB4444TOARGBROW_NEON)
1266   if (TestCpuFlag(kCpuHasNEON)) {
1267     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_NEON;
1268     if (IS_ALIGNED(width, 8)) {
1269       ARGB4444ToARGBRow = ARGB4444ToARGBRow_NEON;
1270     }
1271   }
1272 #endif
1273 #if defined(HAS_ARGB4444TOARGBROW_DSPR2)
1274   if (TestCpuFlag(kCpuHasDSPR2)) {
1275     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_DSPR2;
1276     if (IS_ALIGNED(width, 4)) {
1277       ARGB4444ToARGBRow = ARGB4444ToARGBRow_DSPR2;
1278     }
1279   }
1280 #endif
1281 #if defined(HAS_ARGB4444TOARGBROW_MSA)
1282   if (TestCpuFlag(kCpuHasMSA)) {
1283     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_MSA;
1284     if (IS_ALIGNED(width, 16)) {
1285       ARGB4444ToARGBRow = ARGB4444ToARGBRow_MSA;
1286     }
1287   }
1288 #endif
1289 
1290   for (y = 0; y < height; ++y) {
1291     ARGB4444ToARGBRow(src_argb4444, dst_argb, width);
1292     src_argb4444 += src_stride_argb4444;
1293     dst_argb += dst_stride_argb;
1294   }
1295   return 0;
1296 }
1297 
1298 // Convert NV12 to ARGB.
1299 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)1300 int NV12ToARGB(const uint8* src_y,
1301                int src_stride_y,
1302                const uint8* src_uv,
1303                int src_stride_uv,
1304                uint8* dst_argb,
1305                int dst_stride_argb,
1306                int width,
1307                int height) {
1308   int y;
1309   void (*NV12ToARGBRow)(const uint8* y_buf, const uint8* uv_buf, uint8* rgb_buf,
1310                         const struct YuvConstants* yuvconstants, int width) =
1311       NV12ToARGBRow_C;
1312   if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
1313     return -1;
1314   }
1315   // Negative height means invert the image.
1316   if (height < 0) {
1317     height = -height;
1318     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1319     dst_stride_argb = -dst_stride_argb;
1320   }
1321 #if defined(HAS_NV12TOARGBROW_SSSE3)
1322   if (TestCpuFlag(kCpuHasSSSE3)) {
1323     NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
1324     if (IS_ALIGNED(width, 8)) {
1325       NV12ToARGBRow = NV12ToARGBRow_SSSE3;
1326     }
1327   }
1328 #endif
1329 #if defined(HAS_NV12TOARGBROW_AVX2)
1330   if (TestCpuFlag(kCpuHasAVX2)) {
1331     NV12ToARGBRow = NV12ToARGBRow_Any_AVX2;
1332     if (IS_ALIGNED(width, 16)) {
1333       NV12ToARGBRow = NV12ToARGBRow_AVX2;
1334     }
1335   }
1336 #endif
1337 #if defined(HAS_NV12TOARGBROW_NEON)
1338   if (TestCpuFlag(kCpuHasNEON)) {
1339     NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
1340     if (IS_ALIGNED(width, 8)) {
1341       NV12ToARGBRow = NV12ToARGBRow_NEON;
1342     }
1343   }
1344 #endif
1345 #if defined(HAS_NV12TOARGBROW_DSPR2)
1346   if (TestCpuFlag(kCpuHasDSPR2)) {
1347     NV12ToARGBRow = NV12ToARGBRow_Any_DSPR2;
1348     if (IS_ALIGNED(width, 8)) {
1349       NV12ToARGBRow = NV12ToARGBRow_DSPR2;
1350     }
1351   }
1352 #endif
1353 #if defined(HAS_NV12TOARGBROW_MSA)
1354   if (TestCpuFlag(kCpuHasMSA)) {
1355     NV12ToARGBRow = NV12ToARGBRow_Any_MSA;
1356     if (IS_ALIGNED(width, 8)) {
1357       NV12ToARGBRow = NV12ToARGBRow_MSA;
1358     }
1359   }
1360 #endif
1361 
1362   for (y = 0; y < height; ++y) {
1363     NV12ToARGBRow(src_y, src_uv, dst_argb, &kYuvI601Constants, width);
1364     dst_argb += dst_stride_argb;
1365     src_y += src_stride_y;
1366     if (y & 1) {
1367       src_uv += src_stride_uv;
1368     }
1369   }
1370   return 0;
1371 }
1372 
1373 // Convert NV21 to ARGB.
1374 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)1375 int NV21ToARGB(const uint8* src_y,
1376                int src_stride_y,
1377                const uint8* src_uv,
1378                int src_stride_uv,
1379                uint8* dst_argb,
1380                int dst_stride_argb,
1381                int width,
1382                int height) {
1383   int y;
1384   void (*NV21ToARGBRow)(const uint8* y_buf, const uint8* uv_buf, uint8* rgb_buf,
1385                         const struct YuvConstants* yuvconstants, int width) =
1386       NV21ToARGBRow_C;
1387   if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
1388     return -1;
1389   }
1390   // Negative height means invert the image.
1391   if (height < 0) {
1392     height = -height;
1393     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1394     dst_stride_argb = -dst_stride_argb;
1395   }
1396 #if defined(HAS_NV21TOARGBROW_SSSE3)
1397   if (TestCpuFlag(kCpuHasSSSE3)) {
1398     NV21ToARGBRow = NV21ToARGBRow_Any_SSSE3;
1399     if (IS_ALIGNED(width, 8)) {
1400       NV21ToARGBRow = NV21ToARGBRow_SSSE3;
1401     }
1402   }
1403 #endif
1404 #if defined(HAS_NV21TOARGBROW_AVX2)
1405   if (TestCpuFlag(kCpuHasAVX2)) {
1406     NV21ToARGBRow = NV21ToARGBRow_Any_AVX2;
1407     if (IS_ALIGNED(width, 16)) {
1408       NV21ToARGBRow = NV21ToARGBRow_AVX2;
1409     }
1410   }
1411 #endif
1412 #if defined(HAS_NV21TOARGBROW_NEON)
1413   if (TestCpuFlag(kCpuHasNEON)) {
1414     NV21ToARGBRow = NV21ToARGBRow_Any_NEON;
1415     if (IS_ALIGNED(width, 8)) {
1416       NV21ToARGBRow = NV21ToARGBRow_NEON;
1417     }
1418   }
1419 #endif
1420 #if defined(HAS_NV21TOARGBROW_MSA)
1421   if (TestCpuFlag(kCpuHasMSA)) {
1422     NV21ToARGBRow = NV21ToARGBRow_Any_MSA;
1423     if (IS_ALIGNED(width, 8)) {
1424       NV21ToARGBRow = NV21ToARGBRow_MSA;
1425     }
1426   }
1427 #endif
1428 
1429   for (y = 0; y < height; ++y) {
1430     NV21ToARGBRow(src_y, src_uv, dst_argb, &kYuvI601Constants, width);
1431     dst_argb += dst_stride_argb;
1432     src_y += src_stride_y;
1433     if (y & 1) {
1434       src_uv += src_stride_uv;
1435     }
1436   }
1437   return 0;
1438 }
1439 
1440 // Convert M420 to ARGB.
1441 LIBYUV_API
M420ToARGB(const uint8 * src_m420,int src_stride_m420,uint8 * dst_argb,int dst_stride_argb,int width,int height)1442 int M420ToARGB(const uint8* src_m420,
1443                int src_stride_m420,
1444                uint8* dst_argb,
1445                int dst_stride_argb,
1446                int width,
1447                int height) {
1448   int y;
1449   void (*NV12ToARGBRow)(const uint8* y_buf, const uint8* uv_buf, uint8* rgb_buf,
1450                         const struct YuvConstants* yuvconstants, int width) =
1451       NV12ToARGBRow_C;
1452   if (!src_m420 || !dst_argb || width <= 0 || height == 0) {
1453     return -1;
1454   }
1455   // Negative height means invert the image.
1456   if (height < 0) {
1457     height = -height;
1458     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1459     dst_stride_argb = -dst_stride_argb;
1460   }
1461 #if defined(HAS_NV12TOARGBROW_SSSE3)
1462   if (TestCpuFlag(kCpuHasSSSE3)) {
1463     NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
1464     if (IS_ALIGNED(width, 8)) {
1465       NV12ToARGBRow = NV12ToARGBRow_SSSE3;
1466     }
1467   }
1468 #endif
1469 #if defined(HAS_NV12TOARGBROW_AVX2)
1470   if (TestCpuFlag(kCpuHasAVX2)) {
1471     NV12ToARGBRow = NV12ToARGBRow_Any_AVX2;
1472     if (IS_ALIGNED(width, 16)) {
1473       NV12ToARGBRow = NV12ToARGBRow_AVX2;
1474     }
1475   }
1476 #endif
1477 #if defined(HAS_NV12TOARGBROW_NEON)
1478   if (TestCpuFlag(kCpuHasNEON)) {
1479     NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
1480     if (IS_ALIGNED(width, 8)) {
1481       NV12ToARGBRow = NV12ToARGBRow_NEON;
1482     }
1483   }
1484 #endif
1485 #if defined(HAS_NV12TOARGBROW_DSPR2)
1486   if (TestCpuFlag(kCpuHasDSPR2)) {
1487     NV12ToARGBRow = NV12ToARGBRow_Any_DSPR2;
1488     if (IS_ALIGNED(width, 8)) {
1489       NV12ToARGBRow = NV12ToARGBRow_DSPR2;
1490     }
1491   }
1492 #endif
1493 #if defined(HAS_NV12TOARGBROW_MSA)
1494   if (TestCpuFlag(kCpuHasMSA)) {
1495     NV12ToARGBRow = NV12ToARGBRow_Any_MSA;
1496     if (IS_ALIGNED(width, 8)) {
1497       NV12ToARGBRow = NV12ToARGBRow_MSA;
1498     }
1499   }
1500 #endif
1501 
1502   for (y = 0; y < height - 1; y += 2) {
1503     NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb,
1504                   &kYuvI601Constants, width);
1505     NV12ToARGBRow(src_m420 + src_stride_m420, src_m420 + src_stride_m420 * 2,
1506                   dst_argb + dst_stride_argb, &kYuvI601Constants, width);
1507     dst_argb += dst_stride_argb * 2;
1508     src_m420 += src_stride_m420 * 3;
1509   }
1510   if (height & 1) {
1511     NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb,
1512                   &kYuvI601Constants, width);
1513   }
1514   return 0;
1515 }
1516 
1517 // Convert YUY2 to ARGB.
1518 LIBYUV_API
YUY2ToARGB(const uint8 * src_yuy2,int src_stride_yuy2,uint8 * dst_argb,int dst_stride_argb,int width,int height)1519 int YUY2ToARGB(const uint8* src_yuy2,
1520                int src_stride_yuy2,
1521                uint8* dst_argb,
1522                int dst_stride_argb,
1523                int width,
1524                int height) {
1525   int y;
1526   void (*YUY2ToARGBRow)(const uint8* src_yuy2, uint8* dst_argb,
1527                         const struct YuvConstants* yuvconstants, int width) =
1528       YUY2ToARGBRow_C;
1529   if (!src_yuy2 || !dst_argb || width <= 0 || height == 0) {
1530     return -1;
1531   }
1532   // Negative height means invert the image.
1533   if (height < 0) {
1534     height = -height;
1535     src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
1536     src_stride_yuy2 = -src_stride_yuy2;
1537   }
1538   // Coalesce rows.
1539   if (src_stride_yuy2 == width * 2 && dst_stride_argb == width * 4) {
1540     width *= height;
1541     height = 1;
1542     src_stride_yuy2 = dst_stride_argb = 0;
1543   }
1544 #if defined(HAS_YUY2TOARGBROW_SSSE3)
1545   if (TestCpuFlag(kCpuHasSSSE3)) {
1546     YUY2ToARGBRow = YUY2ToARGBRow_Any_SSSE3;
1547     if (IS_ALIGNED(width, 16)) {
1548       YUY2ToARGBRow = YUY2ToARGBRow_SSSE3;
1549     }
1550   }
1551 #endif
1552 #if defined(HAS_YUY2TOARGBROW_AVX2)
1553   if (TestCpuFlag(kCpuHasAVX2)) {
1554     YUY2ToARGBRow = YUY2ToARGBRow_Any_AVX2;
1555     if (IS_ALIGNED(width, 32)) {
1556       YUY2ToARGBRow = YUY2ToARGBRow_AVX2;
1557     }
1558   }
1559 #endif
1560 #if defined(HAS_YUY2TOARGBROW_NEON)
1561   if (TestCpuFlag(kCpuHasNEON)) {
1562     YUY2ToARGBRow = YUY2ToARGBRow_Any_NEON;
1563     if (IS_ALIGNED(width, 8)) {
1564       YUY2ToARGBRow = YUY2ToARGBRow_NEON;
1565     }
1566   }
1567 #endif
1568 #if defined(HAS_YUY2TOARGBROW_MSA)
1569   if (TestCpuFlag(kCpuHasMSA)) {
1570     YUY2ToARGBRow = YUY2ToARGBRow_Any_MSA;
1571     if (IS_ALIGNED(width, 8)) {
1572       YUY2ToARGBRow = YUY2ToARGBRow_MSA;
1573     }
1574   }
1575 #endif
1576   for (y = 0; y < height; ++y) {
1577     YUY2ToARGBRow(src_yuy2, dst_argb, &kYuvI601Constants, width);
1578     src_yuy2 += src_stride_yuy2;
1579     dst_argb += dst_stride_argb;
1580   }
1581   return 0;
1582 }
1583 
1584 // Convert UYVY to ARGB.
1585 LIBYUV_API
UYVYToARGB(const uint8 * src_uyvy,int src_stride_uyvy,uint8 * dst_argb,int dst_stride_argb,int width,int height)1586 int UYVYToARGB(const uint8* src_uyvy,
1587                int src_stride_uyvy,
1588                uint8* dst_argb,
1589                int dst_stride_argb,
1590                int width,
1591                int height) {
1592   int y;
1593   void (*UYVYToARGBRow)(const uint8* src_uyvy, uint8* dst_argb,
1594                         const struct YuvConstants* yuvconstants, int width) =
1595       UYVYToARGBRow_C;
1596   if (!src_uyvy || !dst_argb || width <= 0 || height == 0) {
1597     return -1;
1598   }
1599   // Negative height means invert the image.
1600   if (height < 0) {
1601     height = -height;
1602     src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
1603     src_stride_uyvy = -src_stride_uyvy;
1604   }
1605   // Coalesce rows.
1606   if (src_stride_uyvy == width * 2 && dst_stride_argb == width * 4) {
1607     width *= height;
1608     height = 1;
1609     src_stride_uyvy = dst_stride_argb = 0;
1610   }
1611 #if defined(HAS_UYVYTOARGBROW_SSSE3)
1612   if (TestCpuFlag(kCpuHasSSSE3)) {
1613     UYVYToARGBRow = UYVYToARGBRow_Any_SSSE3;
1614     if (IS_ALIGNED(width, 16)) {
1615       UYVYToARGBRow = UYVYToARGBRow_SSSE3;
1616     }
1617   }
1618 #endif
1619 #if defined(HAS_UYVYTOARGBROW_AVX2)
1620   if (TestCpuFlag(kCpuHasAVX2)) {
1621     UYVYToARGBRow = UYVYToARGBRow_Any_AVX2;
1622     if (IS_ALIGNED(width, 32)) {
1623       UYVYToARGBRow = UYVYToARGBRow_AVX2;
1624     }
1625   }
1626 #endif
1627 #if defined(HAS_UYVYTOARGBROW_NEON)
1628   if (TestCpuFlag(kCpuHasNEON)) {
1629     UYVYToARGBRow = UYVYToARGBRow_Any_NEON;
1630     if (IS_ALIGNED(width, 8)) {
1631       UYVYToARGBRow = UYVYToARGBRow_NEON;
1632     }
1633   }
1634 #endif
1635 #if defined(HAS_UYVYTOARGBROW_MSA)
1636   if (TestCpuFlag(kCpuHasMSA)) {
1637     UYVYToARGBRow = UYVYToARGBRow_Any_MSA;
1638     if (IS_ALIGNED(width, 8)) {
1639       UYVYToARGBRow = UYVYToARGBRow_MSA;
1640     }
1641   }
1642 #endif
1643   for (y = 0; y < height; ++y) {
1644     UYVYToARGBRow(src_uyvy, dst_argb, &kYuvI601Constants, width);
1645     src_uyvy += src_stride_uyvy;
1646     dst_argb += dst_stride_argb;
1647   }
1648   return 0;
1649 }
1650 
1651 #ifdef __cplusplus
1652 }  // extern "C"
1653 }  // namespace libyuv
1654 #endif
1655