• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <assert.h>
14 
15 #include "libyuv/convert_from_argb.h"
16 #include "libyuv/cpu_id.h"
17 #ifdef HAVE_JPEG
18 #include "libyuv/mjpeg_decoder.h"
19 #endif
20 #include "libyuv/planar_functions.h"  // For CopyPlane and ARGBShuffle.
21 #include "libyuv/rotate_argb.h"
22 #include "libyuv/row.h"
23 #include "libyuv/scale_row.h"  // For ScaleRowUp2_Linear and ScaleRowUp2_Bilinear
24 #include "libyuv/video_common.h"
25 
26 #ifdef __cplusplus
27 namespace libyuv {
28 extern "C" {
29 #endif
30 
31 // Copy ARGB with optional flipping
32 LIBYUV_API
ARGBCopy(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_argb,int dst_stride_argb,int width,int height)33 int ARGBCopy(const uint8_t* src_argb,
34              int src_stride_argb,
35              uint8_t* dst_argb,
36              int dst_stride_argb,
37              int width,
38              int height) {
39   if (!src_argb || !dst_argb || width <= 0 || height == 0) {
40     return -1;
41   }
42   // Negative height means invert the image.
43   if (height < 0) {
44     height = -height;
45     src_argb = src_argb + (height - 1) * src_stride_argb;
46     src_stride_argb = -src_stride_argb;
47   }
48 
49   CopyPlane(src_argb, src_stride_argb, dst_argb, dst_stride_argb, width * 4,
50             height);
51   return 0;
52 }
53 
54 // Convert I420 to ARGB with matrix.
55 LIBYUV_API
I420ToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)56 int I420ToARGBMatrix(const uint8_t* src_y,
57                      int src_stride_y,
58                      const uint8_t* src_u,
59                      int src_stride_u,
60                      const uint8_t* src_v,
61                      int src_stride_v,
62                      uint8_t* dst_argb,
63                      int dst_stride_argb,
64                      const struct YuvConstants* yuvconstants,
65                      int width,
66                      int height) {
67   int y;
68   void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
69                         const uint8_t* v_buf, uint8_t* rgb_buf,
70                         const struct YuvConstants* yuvconstants, int width) =
71       I422ToARGBRow_C;
72   assert(yuvconstants);
73   if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
74     return -1;
75   }
76   // Negative height means invert the image.
77   if (height < 0) {
78     height = -height;
79     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
80     dst_stride_argb = -dst_stride_argb;
81   }
82 #if defined(HAS_I422TOARGBROW_SSSE3)
83   if (TestCpuFlag(kCpuHasSSSE3)) {
84     I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
85     if (IS_ALIGNED(width, 8)) {
86       I422ToARGBRow = I422ToARGBRow_SSSE3;
87     }
88   }
89 #endif
90 #if defined(HAS_I422TOARGBROW_AVX2)
91   if (TestCpuFlag(kCpuHasAVX2)) {
92     I422ToARGBRow = I422ToARGBRow_Any_AVX2;
93     if (IS_ALIGNED(width, 16)) {
94       I422ToARGBRow = I422ToARGBRow_AVX2;
95     }
96   }
97 #endif
98 #if defined(HAS_I422TOARGBROW_AVX512BW)
99   if (TestCpuFlag(kCpuHasAVX512BW | kCpuHasAVX512VL) ==
100       (kCpuHasAVX512BW | kCpuHasAVX512VL)) {
101     I422ToARGBRow = I422ToARGBRow_Any_AVX512BW;
102     if (IS_ALIGNED(width, 32)) {
103       I422ToARGBRow = I422ToARGBRow_AVX512BW;
104     }
105   }
106 #endif
107 #if defined(HAS_I422TOARGBROW_NEON)
108   if (TestCpuFlag(kCpuHasNEON)) {
109     I422ToARGBRow = I422ToARGBRow_Any_NEON;
110     if (IS_ALIGNED(width, 8)) {
111       I422ToARGBRow = I422ToARGBRow_NEON;
112     }
113   }
114 #endif
115 #if defined(HAS_I422TOARGBROW_MSA)
116   if (TestCpuFlag(kCpuHasMSA)) {
117     I422ToARGBRow = I422ToARGBRow_Any_MSA;
118     if (IS_ALIGNED(width, 8)) {
119       I422ToARGBRow = I422ToARGBRow_MSA;
120     }
121   }
122 #endif
123 #if defined(HAS_I422TOARGBROW_LSX)
124   if (TestCpuFlag(kCpuHasLSX)) {
125     I422ToARGBRow = I422ToARGBRow_Any_LSX;
126     if (IS_ALIGNED(width, 16)) {
127       I422ToARGBRow = I422ToARGBRow_LSX;
128     }
129   }
130 #endif
131 #if defined(HAS_I422TOARGBROW_LASX)
132   if (TestCpuFlag(kCpuHasLASX)) {
133     I422ToARGBRow = I422ToARGBRow_Any_LASX;
134     if (IS_ALIGNED(width, 32)) {
135       I422ToARGBRow = I422ToARGBRow_LASX;
136     }
137   }
138 #endif
139 #if defined(HAS_I422TOARGBROW_RVV)
140   if (TestCpuFlag(kCpuHasRVV)) {
141     I422ToARGBRow = I422ToARGBRow_RVV;
142   }
143 #endif
144 
145   for (y = 0; y < height; ++y) {
146     I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
147     dst_argb += dst_stride_argb;
148     src_y += src_stride_y;
149     if (y & 1) {
150       src_u += src_stride_u;
151       src_v += src_stride_v;
152     }
153   }
154   return 0;
155 }
156 
157 // Convert I420 to ARGB.
158 LIBYUV_API
I420ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)159 int I420ToARGB(const uint8_t* src_y,
160                int src_stride_y,
161                const uint8_t* src_u,
162                int src_stride_u,
163                const uint8_t* src_v,
164                int src_stride_v,
165                uint8_t* dst_argb,
166                int dst_stride_argb,
167                int width,
168                int height) {
169   return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
170                           src_stride_v, dst_argb, dst_stride_argb,
171                           &kYuvI601Constants, width, height);
172 }
173 
174 // Convert I420 to ABGR.
175 LIBYUV_API
I420ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)176 int I420ToABGR(const uint8_t* src_y,
177                int src_stride_y,
178                const uint8_t* src_u,
179                int src_stride_u,
180                const uint8_t* src_v,
181                int src_stride_v,
182                uint8_t* dst_abgr,
183                int dst_stride_abgr,
184                int width,
185                int height) {
186   return I420ToARGBMatrix(src_y, src_stride_y, src_v,
187                           src_stride_v,  // Swap U and V
188                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
189                           &kYvuI601Constants,  // Use Yvu matrix
190                           width, height);
191 }
192 
193 // Convert J420 to ARGB.
194 LIBYUV_API
J420ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)195 int J420ToARGB(const uint8_t* src_y,
196                int src_stride_y,
197                const uint8_t* src_u,
198                int src_stride_u,
199                const uint8_t* src_v,
200                int src_stride_v,
201                uint8_t* dst_argb,
202                int dst_stride_argb,
203                int width,
204                int height) {
205   return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
206                           src_stride_v, dst_argb, dst_stride_argb,
207                           &kYuvJPEGConstants, width, height);
208 }
209 
210 // Convert J420 to ABGR.
211 LIBYUV_API
J420ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)212 int J420ToABGR(const uint8_t* src_y,
213                int src_stride_y,
214                const uint8_t* src_u,
215                int src_stride_u,
216                const uint8_t* src_v,
217                int src_stride_v,
218                uint8_t* dst_abgr,
219                int dst_stride_abgr,
220                int width,
221                int height) {
222   return I420ToARGBMatrix(src_y, src_stride_y, src_v,
223                           src_stride_v,  // Swap U and V
224                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
225                           &kYvuJPEGConstants,  // Use Yvu matrix
226                           width, height);
227 }
228 
229 // Convert H420 to ARGB.
230 LIBYUV_API
H420ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)231 int H420ToARGB(const uint8_t* src_y,
232                int src_stride_y,
233                const uint8_t* src_u,
234                int src_stride_u,
235                const uint8_t* src_v,
236                int src_stride_v,
237                uint8_t* dst_argb,
238                int dst_stride_argb,
239                int width,
240                int height) {
241   return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
242                           src_stride_v, dst_argb, dst_stride_argb,
243                           &kYuvH709Constants, width, height);
244 }
245 
246 // Convert H420 to ABGR.
247 LIBYUV_API
H420ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)248 int H420ToABGR(const uint8_t* src_y,
249                int src_stride_y,
250                const uint8_t* src_u,
251                int src_stride_u,
252                const uint8_t* src_v,
253                int src_stride_v,
254                uint8_t* dst_abgr,
255                int dst_stride_abgr,
256                int width,
257                int height) {
258   return I420ToARGBMatrix(src_y, src_stride_y, src_v,
259                           src_stride_v,  // Swap U and V
260                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
261                           &kYvuH709Constants,  // Use Yvu matrix
262                           width, height);
263 }
264 
265 // Convert U420 to ARGB.
266 LIBYUV_API
U420ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)267 int U420ToARGB(const uint8_t* src_y,
268                int src_stride_y,
269                const uint8_t* src_u,
270                int src_stride_u,
271                const uint8_t* src_v,
272                int src_stride_v,
273                uint8_t* dst_argb,
274                int dst_stride_argb,
275                int width,
276                int height) {
277   return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
278                           src_stride_v, dst_argb, dst_stride_argb,
279                           &kYuv2020Constants, width, height);
280 }
281 
282 // Convert U420 to ABGR.
283 LIBYUV_API
U420ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)284 int U420ToABGR(const uint8_t* src_y,
285                int src_stride_y,
286                const uint8_t* src_u,
287                int src_stride_u,
288                const uint8_t* src_v,
289                int src_stride_v,
290                uint8_t* dst_abgr,
291                int dst_stride_abgr,
292                int width,
293                int height) {
294   return I420ToARGBMatrix(src_y, src_stride_y, src_v,
295                           src_stride_v,  // Swap U and V
296                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
297                           &kYvu2020Constants,  // Use Yvu matrix
298                           width, height);
299 }
300 
301 // Convert I422 to ARGB with matrix.
302 LIBYUV_API
I422ToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)303 int I422ToARGBMatrix(const uint8_t* src_y,
304                      int src_stride_y,
305                      const uint8_t* src_u,
306                      int src_stride_u,
307                      const uint8_t* src_v,
308                      int src_stride_v,
309                      uint8_t* dst_argb,
310                      int dst_stride_argb,
311                      const struct YuvConstants* yuvconstants,
312                      int width,
313                      int height) {
314   int y;
315   void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
316                         const uint8_t* v_buf, uint8_t* rgb_buf,
317                         const struct YuvConstants* yuvconstants, int width) =
318       I422ToARGBRow_C;
319   assert(yuvconstants);
320   if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
321     return -1;
322   }
323   // Negative height means invert the image.
324   if (height < 0) {
325     height = -height;
326     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
327     dst_stride_argb = -dst_stride_argb;
328   }
329   // Coalesce rows.
330   if (src_stride_y == width && src_stride_u * 2 == width &&
331       src_stride_v * 2 == width && dst_stride_argb == width * 4) {
332     width *= height;
333     height = 1;
334     src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
335   }
336 #if defined(HAS_I422TOARGBROW_SSSE3)
337   if (TestCpuFlag(kCpuHasSSSE3)) {
338     I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
339     if (IS_ALIGNED(width, 8)) {
340       I422ToARGBRow = I422ToARGBRow_SSSE3;
341     }
342   }
343 #endif
344 #if defined(HAS_I422TOARGBROW_AVX2)
345   if (TestCpuFlag(kCpuHasAVX2)) {
346     I422ToARGBRow = I422ToARGBRow_Any_AVX2;
347     if (IS_ALIGNED(width, 16)) {
348       I422ToARGBRow = I422ToARGBRow_AVX2;
349     }
350   }
351 #endif
352 #if defined(HAS_I422TOARGBROW_AVX512BW)
353   if (TestCpuFlag(kCpuHasAVX512BW | kCpuHasAVX512VL) ==
354       (kCpuHasAVX512BW | kCpuHasAVX512VL)) {
355     I422ToARGBRow = I422ToARGBRow_Any_AVX512BW;
356     if (IS_ALIGNED(width, 32)) {
357       I422ToARGBRow = I422ToARGBRow_AVX512BW;
358     }
359   }
360 #endif
361 #if defined(HAS_I422TOARGBROW_NEON)
362   if (TestCpuFlag(kCpuHasNEON)) {
363     I422ToARGBRow = I422ToARGBRow_Any_NEON;
364     if (IS_ALIGNED(width, 8)) {
365       I422ToARGBRow = I422ToARGBRow_NEON;
366     }
367   }
368 #endif
369 #if defined(HAS_I422TOARGBROW_MSA)
370   if (TestCpuFlag(kCpuHasMSA)) {
371     I422ToARGBRow = I422ToARGBRow_Any_MSA;
372     if (IS_ALIGNED(width, 8)) {
373       I422ToARGBRow = I422ToARGBRow_MSA;
374     }
375   }
376 #endif
377 #if defined(HAS_I422TOARGBROW_LSX)
378   if (TestCpuFlag(kCpuHasLSX)) {
379     I422ToARGBRow = I422ToARGBRow_Any_LSX;
380     if (IS_ALIGNED(width, 16)) {
381       I422ToARGBRow = I422ToARGBRow_LSX;
382     }
383   }
384 #endif
385 #if defined(HAS_I422TOARGBROW_LASX)
386   if (TestCpuFlag(kCpuHasLASX)) {
387     I422ToARGBRow = I422ToARGBRow_Any_LASX;
388     if (IS_ALIGNED(width, 32)) {
389       I422ToARGBRow = I422ToARGBRow_LASX;
390     }
391   }
392 #endif
393 #if defined(HAS_I422TOARGBROW_RVV)
394   if (TestCpuFlag(kCpuHasRVV)) {
395     I422ToARGBRow = I422ToARGBRow_RVV;
396   }
397 #endif
398 
399   for (y = 0; y < height; ++y) {
400     I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
401     dst_argb += dst_stride_argb;
402     src_y += src_stride_y;
403     src_u += src_stride_u;
404     src_v += src_stride_v;
405   }
406   return 0;
407 }
408 
409 // Convert I422 to ARGB.
410 LIBYUV_API
I422ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)411 int I422ToARGB(const uint8_t* src_y,
412                int src_stride_y,
413                const uint8_t* src_u,
414                int src_stride_u,
415                const uint8_t* src_v,
416                int src_stride_v,
417                uint8_t* dst_argb,
418                int dst_stride_argb,
419                int width,
420                int height) {
421   return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
422                           src_stride_v, dst_argb, dst_stride_argb,
423                           &kYuvI601Constants, width, height);
424 }
425 
426 // Convert I422 to ABGR.
427 LIBYUV_API
I422ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)428 int I422ToABGR(const uint8_t* src_y,
429                int src_stride_y,
430                const uint8_t* src_u,
431                int src_stride_u,
432                const uint8_t* src_v,
433                int src_stride_v,
434                uint8_t* dst_abgr,
435                int dst_stride_abgr,
436                int width,
437                int height) {
438   return I422ToARGBMatrix(src_y, src_stride_y, src_v,
439                           src_stride_v,  // Swap U and V
440                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
441                           &kYvuI601Constants,  // Use Yvu matrix
442                           width, height);
443 }
444 
445 // Convert J422 to ARGB.
446 LIBYUV_API
J422ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)447 int J422ToARGB(const uint8_t* src_y,
448                int src_stride_y,
449                const uint8_t* src_u,
450                int src_stride_u,
451                const uint8_t* src_v,
452                int src_stride_v,
453                uint8_t* dst_argb,
454                int dst_stride_argb,
455                int width,
456                int height) {
457   return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
458                           src_stride_v, dst_argb, dst_stride_argb,
459                           &kYuvJPEGConstants, width, height);
460 }
461 
462 // Convert J422 to ABGR.
463 LIBYUV_API
J422ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)464 int J422ToABGR(const uint8_t* src_y,
465                int src_stride_y,
466                const uint8_t* src_u,
467                int src_stride_u,
468                const uint8_t* src_v,
469                int src_stride_v,
470                uint8_t* dst_abgr,
471                int dst_stride_abgr,
472                int width,
473                int height) {
474   return I422ToARGBMatrix(src_y, src_stride_y, src_v,
475                           src_stride_v,  // Swap U and V
476                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
477                           &kYvuJPEGConstants,  // Use Yvu matrix
478                           width, height);
479 }
480 
481 // Convert H422 to ARGB.
482 LIBYUV_API
H422ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)483 int H422ToARGB(const uint8_t* src_y,
484                int src_stride_y,
485                const uint8_t* src_u,
486                int src_stride_u,
487                const uint8_t* src_v,
488                int src_stride_v,
489                uint8_t* dst_argb,
490                int dst_stride_argb,
491                int width,
492                int height) {
493   return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
494                           src_stride_v, dst_argb, dst_stride_argb,
495                           &kYuvH709Constants, width, height);
496 }
497 
498 // Convert H422 to ABGR.
499 LIBYUV_API
H422ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)500 int H422ToABGR(const uint8_t* src_y,
501                int src_stride_y,
502                const uint8_t* src_u,
503                int src_stride_u,
504                const uint8_t* src_v,
505                int src_stride_v,
506                uint8_t* dst_abgr,
507                int dst_stride_abgr,
508                int width,
509                int height) {
510   return I422ToARGBMatrix(src_y, src_stride_y, src_v,
511                           src_stride_v,  // Swap U and V
512                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
513                           &kYvuH709Constants,  // Use Yvu matrix
514                           width, height);
515 }
516 
517 // Convert U422 to ARGB.
518 LIBYUV_API
U422ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)519 int U422ToARGB(const uint8_t* src_y,
520                int src_stride_y,
521                const uint8_t* src_u,
522                int src_stride_u,
523                const uint8_t* src_v,
524                int src_stride_v,
525                uint8_t* dst_argb,
526                int dst_stride_argb,
527                int width,
528                int height) {
529   return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
530                           src_stride_v, dst_argb, dst_stride_argb,
531                           &kYuv2020Constants, width, height);
532 }
533 
534 // Convert U422 to ABGR.
535 LIBYUV_API
U422ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)536 int U422ToABGR(const uint8_t* src_y,
537                int src_stride_y,
538                const uint8_t* src_u,
539                int src_stride_u,
540                const uint8_t* src_v,
541                int src_stride_v,
542                uint8_t* dst_abgr,
543                int dst_stride_abgr,
544                int width,
545                int height) {
546   return I422ToARGBMatrix(src_y, src_stride_y, src_v,
547                           src_stride_v,  // Swap U and V
548                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
549                           &kYvu2020Constants,  // Use Yvu matrix
550                           width, height);
551 }
552 
553 // Convert I444 to ARGB with matrix.
554 LIBYUV_API
I444ToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)555 int I444ToARGBMatrix(const uint8_t* src_y,
556                      int src_stride_y,
557                      const uint8_t* src_u,
558                      int src_stride_u,
559                      const uint8_t* src_v,
560                      int src_stride_v,
561                      uint8_t* dst_argb,
562                      int dst_stride_argb,
563                      const struct YuvConstants* yuvconstants,
564                      int width,
565                      int height) {
566   int y;
567   void (*I444ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
568                         const uint8_t* v_buf, uint8_t* rgb_buf,
569                         const struct YuvConstants* yuvconstants, int width) =
570       I444ToARGBRow_C;
571   assert(yuvconstants);
572   if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
573     return -1;
574   }
575   // Negative height means invert the image.
576   if (height < 0) {
577     height = -height;
578     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
579     dst_stride_argb = -dst_stride_argb;
580   }
581   // Coalesce rows.
582   if (src_stride_y == width && src_stride_u == width && src_stride_v == width &&
583       dst_stride_argb == width * 4) {
584     width *= height;
585     height = 1;
586     src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
587   }
588 #if defined(HAS_I444TOARGBROW_SSSE3)
589   if (TestCpuFlag(kCpuHasSSSE3)) {
590     I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
591     if (IS_ALIGNED(width, 8)) {
592       I444ToARGBRow = I444ToARGBRow_SSSE3;
593     }
594   }
595 #endif
596 #if defined(HAS_I444TOARGBROW_AVX2)
597   if (TestCpuFlag(kCpuHasAVX2)) {
598     I444ToARGBRow = I444ToARGBRow_Any_AVX2;
599     if (IS_ALIGNED(width, 16)) {
600       I444ToARGBRow = I444ToARGBRow_AVX2;
601     }
602   }
603 #endif
604 #if defined(HAS_I444TOARGBROW_NEON)
605   if (TestCpuFlag(kCpuHasNEON)) {
606     I444ToARGBRow = I444ToARGBRow_Any_NEON;
607     if (IS_ALIGNED(width, 8)) {
608       I444ToARGBRow = I444ToARGBRow_NEON;
609     }
610   }
611 #endif
612 #if defined(HAS_I444TOARGBROW_MSA)
613   if (TestCpuFlag(kCpuHasMSA)) {
614     I444ToARGBRow = I444ToARGBRow_Any_MSA;
615     if (IS_ALIGNED(width, 8)) {
616       I444ToARGBRow = I444ToARGBRow_MSA;
617     }
618   }
619 #endif
620 #if defined(HAS_I444TOARGBROW_LSX)
621   if (TestCpuFlag(kCpuHasLSX)) {
622     I444ToARGBRow = I444ToARGBRow_Any_LSX;
623     if (IS_ALIGNED(width, 16)) {
624       I444ToARGBRow = I444ToARGBRow_LSX;
625     }
626   }
627 #endif
628 #if defined(HAS_I444TOARGBROW_RVV)
629   if (TestCpuFlag(kCpuHasRVV)) {
630     I444ToARGBRow = I444ToARGBRow_RVV;
631   }
632 #endif
633 
634   for (y = 0; y < height; ++y) {
635     I444ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
636     dst_argb += dst_stride_argb;
637     src_y += src_stride_y;
638     src_u += src_stride_u;
639     src_v += src_stride_v;
640   }
641   return 0;
642 }
643 
644 // Convert I444 to ARGB.
645 LIBYUV_API
I444ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)646 int I444ToARGB(const uint8_t* src_y,
647                int src_stride_y,
648                const uint8_t* src_u,
649                int src_stride_u,
650                const uint8_t* src_v,
651                int src_stride_v,
652                uint8_t* dst_argb,
653                int dst_stride_argb,
654                int width,
655                int height) {
656   return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
657                           src_stride_v, dst_argb, dst_stride_argb,
658                           &kYuvI601Constants, width, height);
659 }
660 
661 // Convert I444 to ABGR.
662 LIBYUV_API
I444ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)663 int I444ToABGR(const uint8_t* src_y,
664                int src_stride_y,
665                const uint8_t* src_u,
666                int src_stride_u,
667                const uint8_t* src_v,
668                int src_stride_v,
669                uint8_t* dst_abgr,
670                int dst_stride_abgr,
671                int width,
672                int height) {
673   return I444ToARGBMatrix(src_y, src_stride_y, src_v,
674                           src_stride_v,  // Swap U and V
675                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
676                           &kYvuI601Constants,  // Use Yvu matrix
677                           width, height);
678 }
679 
680 // Convert J444 to ARGB.
681 LIBYUV_API
J444ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)682 int J444ToARGB(const uint8_t* src_y,
683                int src_stride_y,
684                const uint8_t* src_u,
685                int src_stride_u,
686                const uint8_t* src_v,
687                int src_stride_v,
688                uint8_t* dst_argb,
689                int dst_stride_argb,
690                int width,
691                int height) {
692   return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
693                           src_stride_v, dst_argb, dst_stride_argb,
694                           &kYuvJPEGConstants, width, height);
695 }
696 
697 // Convert J444 to ABGR.
698 LIBYUV_API
J444ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)699 int J444ToABGR(const uint8_t* src_y,
700                int src_stride_y,
701                const uint8_t* src_u,
702                int src_stride_u,
703                const uint8_t* src_v,
704                int src_stride_v,
705                uint8_t* dst_abgr,
706                int dst_stride_abgr,
707                int width,
708                int height) {
709   return I444ToARGBMatrix(src_y, src_stride_y, src_v,
710                           src_stride_v,  // Swap U and V
711                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
712                           &kYvuJPEGConstants,  // Use Yvu matrix
713                           width, height);
714 }
715 
716 // Convert H444 to ARGB.
717 LIBYUV_API
H444ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)718 int H444ToARGB(const uint8_t* src_y,
719                int src_stride_y,
720                const uint8_t* src_u,
721                int src_stride_u,
722                const uint8_t* src_v,
723                int src_stride_v,
724                uint8_t* dst_argb,
725                int dst_stride_argb,
726                int width,
727                int height) {
728   return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
729                           src_stride_v, dst_argb, dst_stride_argb,
730                           &kYuvH709Constants, width, height);
731 }
732 
733 // Convert H444 to ABGR.
734 LIBYUV_API
H444ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)735 int H444ToABGR(const uint8_t* src_y,
736                int src_stride_y,
737                const uint8_t* src_u,
738                int src_stride_u,
739                const uint8_t* src_v,
740                int src_stride_v,
741                uint8_t* dst_abgr,
742                int dst_stride_abgr,
743                int width,
744                int height) {
745   return I444ToARGBMatrix(src_y, src_stride_y, src_v,
746                           src_stride_v,  // Swap U and V
747                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
748                           &kYvuH709Constants,  // Use Yvu matrix
749                           width, height);
750 }
751 
752 // Convert U444 to ARGB.
753 LIBYUV_API
U444ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)754 int U444ToARGB(const uint8_t* src_y,
755                int src_stride_y,
756                const uint8_t* src_u,
757                int src_stride_u,
758                const uint8_t* src_v,
759                int src_stride_v,
760                uint8_t* dst_argb,
761                int dst_stride_argb,
762                int width,
763                int height) {
764   return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
765                           src_stride_v, dst_argb, dst_stride_argb,
766                           &kYuv2020Constants, width, height);
767 }
768 
769 // Convert U444 to ABGR.
770 LIBYUV_API
U444ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)771 int U444ToABGR(const uint8_t* src_y,
772                int src_stride_y,
773                const uint8_t* src_u,
774                int src_stride_u,
775                const uint8_t* src_v,
776                int src_stride_v,
777                uint8_t* dst_abgr,
778                int dst_stride_abgr,
779                int width,
780                int height) {
781   return I444ToARGBMatrix(src_y, src_stride_y, src_v,
782                           src_stride_v,  // Swap U and V
783                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
784                           &kYvu2020Constants,  // Use Yvu matrix
785                           width, height);
786 }
787 
788 // Convert I444 to RGB24 with matrix.
789 LIBYUV_API
I444ToRGB24Matrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgb24,int dst_stride_rgb24,const struct YuvConstants * yuvconstants,int width,int height)790 int I444ToRGB24Matrix(const uint8_t* src_y,
791                       int src_stride_y,
792                       const uint8_t* src_u,
793                       int src_stride_u,
794                       const uint8_t* src_v,
795                       int src_stride_v,
796                       uint8_t* dst_rgb24,
797                       int dst_stride_rgb24,
798                       const struct YuvConstants* yuvconstants,
799                       int width,
800                       int height) {
801   int y;
802   void (*I444ToRGB24Row)(const uint8_t* y_buf, const uint8_t* u_buf,
803                          const uint8_t* v_buf, uint8_t* rgb_buf,
804                          const struct YuvConstants* yuvconstants, int width) =
805       I444ToRGB24Row_C;
806   assert(yuvconstants);
807   if (!src_y || !src_u || !src_v || !dst_rgb24 || width <= 0 || height == 0) {
808     return -1;
809   }
810   // Negative height means invert the image.
811   if (height < 0) {
812     height = -height;
813     dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
814     dst_stride_rgb24 = -dst_stride_rgb24;
815   }
816   // Coalesce rows.
817   if (src_stride_y == width && src_stride_u == width && src_stride_v == width &&
818       dst_stride_rgb24 == width * 3) {
819     width *= height;
820     height = 1;
821     src_stride_y = src_stride_u = src_stride_v = dst_stride_rgb24 = 0;
822   }
823 #if defined(HAS_I444TORGB24ROW_SSSE3)
824   if (TestCpuFlag(kCpuHasSSSE3)) {
825     I444ToRGB24Row = I444ToRGB24Row_Any_SSSE3;
826     if (IS_ALIGNED(width, 16)) {
827       I444ToRGB24Row = I444ToRGB24Row_SSSE3;
828     }
829   }
830 #endif
831 #if defined(HAS_I444TORGB24ROW_AVX2)
832   if (TestCpuFlag(kCpuHasAVX2)) {
833     I444ToRGB24Row = I444ToRGB24Row_Any_AVX2;
834     if (IS_ALIGNED(width, 32)) {
835       I444ToRGB24Row = I444ToRGB24Row_AVX2;
836     }
837   }
838 #endif
839 #if defined(HAS_I444TORGB24ROW_NEON)
840   if (TestCpuFlag(kCpuHasNEON)) {
841     I444ToRGB24Row = I444ToRGB24Row_Any_NEON;
842     if (IS_ALIGNED(width, 8)) {
843       I444ToRGB24Row = I444ToRGB24Row_NEON;
844     }
845   }
846 #endif
847 #if defined(HAS_I444TORGB24ROW_MSA)
848   if (TestCpuFlag(kCpuHasMSA)) {
849     I444ToRGB24Row = I444ToRGB24Row_Any_MSA;
850     if (IS_ALIGNED(width, 8)) {
851       I444ToRGB24Row = I444ToRGB24Row_MSA;
852     }
853   }
854 #endif
855 #if defined(HAS_I444TORGB24ROW_LSX)
856   if (TestCpuFlag(kCpuHasLSX)) {
857     I444ToRGB24Row = I444ToRGB24Row_Any_LSX;
858     if (IS_ALIGNED(width, 16)) {
859       I444ToRGB24Row = I444ToRGB24Row_LSX;
860     }
861   }
862 #endif
863 #if defined(HAS_I444TORGB24ROW_RVV)
864   if (TestCpuFlag(kCpuHasRVV)) {
865     I444ToRGB24Row = I444ToRGB24Row_RVV;
866   }
867 #endif
868 
869   for (y = 0; y < height; ++y) {
870     I444ToRGB24Row(src_y, src_u, src_v, dst_rgb24, yuvconstants, width);
871     dst_rgb24 += dst_stride_rgb24;
872     src_y += src_stride_y;
873     src_u += src_stride_u;
874     src_v += src_stride_v;
875   }
876   return 0;
877 }
878 
879 // Convert I444 to RGB24.
880 LIBYUV_API
I444ToRGB24(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgb24,int dst_stride_rgb24,int width,int height)881 int I444ToRGB24(const uint8_t* src_y,
882                 int src_stride_y,
883                 const uint8_t* src_u,
884                 int src_stride_u,
885                 const uint8_t* src_v,
886                 int src_stride_v,
887                 uint8_t* dst_rgb24,
888                 int dst_stride_rgb24,
889                 int width,
890                 int height) {
891   return I444ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
892                            src_stride_v, dst_rgb24, dst_stride_rgb24,
893                            &kYuvI601Constants, width, height);
894 }
895 
896 // Convert I444 to RAW.
897 LIBYUV_API
I444ToRAW(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_raw,int dst_stride_raw,int width,int height)898 int I444ToRAW(const uint8_t* src_y,
899               int src_stride_y,
900               const uint8_t* src_u,
901               int src_stride_u,
902               const uint8_t* src_v,
903               int src_stride_v,
904               uint8_t* dst_raw,
905               int dst_stride_raw,
906               int width,
907               int height) {
908   return I444ToRGB24Matrix(src_y, src_stride_y, src_v,
909                            src_stride_v,  // Swap U and V
910                            src_u, src_stride_u, dst_raw, dst_stride_raw,
911                            &kYvuI601Constants,  // Use Yvu matrix
912                            width, height);
913 }
914 
915 // Convert 10 bit YUV to ARGB with matrix.
916 // TODO(fbarchard): Consider passing scale multiplier to I210ToARGB to
917 // multiply 10 bit yuv into high bits to allow any number of bits.
918 LIBYUV_API
I010ToAR30Matrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height)919 int I010ToAR30Matrix(const uint16_t* src_y,
920                      int src_stride_y,
921                      const uint16_t* src_u,
922                      int src_stride_u,
923                      const uint16_t* src_v,
924                      int src_stride_v,
925                      uint8_t* dst_ar30,
926                      int dst_stride_ar30,
927                      const struct YuvConstants* yuvconstants,
928                      int width,
929                      int height) {
930   int y;
931   void (*I210ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
932                         const uint16_t* v_buf, uint8_t* rgb_buf,
933                         const struct YuvConstants* yuvconstants, int width) =
934       I210ToAR30Row_C;
935   assert(yuvconstants);
936   if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
937     return -1;
938   }
939   // Negative height means invert the image.
940   if (height < 0) {
941     height = -height;
942     dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
943     dst_stride_ar30 = -dst_stride_ar30;
944   }
945 #if defined(HAS_I210TOAR30ROW_SSSE3)
946   if (TestCpuFlag(kCpuHasSSSE3)) {
947     I210ToAR30Row = I210ToAR30Row_Any_SSSE3;
948     if (IS_ALIGNED(width, 8)) {
949       I210ToAR30Row = I210ToAR30Row_SSSE3;
950     }
951   }
952 #endif
953 #if defined(HAS_I210TOAR30ROW_AVX2)
954   if (TestCpuFlag(kCpuHasAVX2)) {
955     I210ToAR30Row = I210ToAR30Row_Any_AVX2;
956     if (IS_ALIGNED(width, 16)) {
957       I210ToAR30Row = I210ToAR30Row_AVX2;
958     }
959   }
960 #endif
961   for (y = 0; y < height; ++y) {
962     I210ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
963     dst_ar30 += dst_stride_ar30;
964     src_y += src_stride_y;
965     if (y & 1) {
966       src_u += src_stride_u;
967       src_v += src_stride_v;
968     }
969   }
970   return 0;
971 }
972 
973 // Convert I010 to AR30.
974 LIBYUV_API
I010ToAR30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,int width,int height)975 int I010ToAR30(const uint16_t* src_y,
976                int src_stride_y,
977                const uint16_t* src_u,
978                int src_stride_u,
979                const uint16_t* src_v,
980                int src_stride_v,
981                uint8_t* dst_ar30,
982                int dst_stride_ar30,
983                int width,
984                int height) {
985   return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
986                           src_stride_v, dst_ar30, dst_stride_ar30,
987                           &kYuvI601Constants, width, height);
988 }
989 
990 // Convert H010 to AR30.
991 LIBYUV_API
H010ToAR30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,int width,int height)992 int H010ToAR30(const uint16_t* src_y,
993                int src_stride_y,
994                const uint16_t* src_u,
995                int src_stride_u,
996                const uint16_t* src_v,
997                int src_stride_v,
998                uint8_t* dst_ar30,
999                int dst_stride_ar30,
1000                int width,
1001                int height) {
1002   return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1003                           src_stride_v, dst_ar30, dst_stride_ar30,
1004                           &kYuvH709Constants, width, height);
1005 }
1006 
1007 // Convert U010 to AR30.
1008 LIBYUV_API
U010ToAR30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,int width,int height)1009 int U010ToAR30(const uint16_t* src_y,
1010                int src_stride_y,
1011                const uint16_t* src_u,
1012                int src_stride_u,
1013                const uint16_t* src_v,
1014                int src_stride_v,
1015                uint8_t* dst_ar30,
1016                int dst_stride_ar30,
1017                int width,
1018                int height) {
1019   return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1020                           src_stride_v, dst_ar30, dst_stride_ar30,
1021                           &kYuv2020Constants, width, height);
1022 }
1023 
1024 // Convert I010 to AB30.
1025 LIBYUV_API
I010ToAB30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)1026 int I010ToAB30(const uint16_t* src_y,
1027                int src_stride_y,
1028                const uint16_t* src_u,
1029                int src_stride_u,
1030                const uint16_t* src_v,
1031                int src_stride_v,
1032                uint8_t* dst_ab30,
1033                int dst_stride_ab30,
1034                int width,
1035                int height) {
1036   return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1037                           src_stride_u, dst_ab30, dst_stride_ab30,
1038                           &kYvuI601Constants, width, height);
1039 }
1040 
1041 // Convert H010 to AB30.
1042 LIBYUV_API
H010ToAB30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)1043 int H010ToAB30(const uint16_t* src_y,
1044                int src_stride_y,
1045                const uint16_t* src_u,
1046                int src_stride_u,
1047                const uint16_t* src_v,
1048                int src_stride_v,
1049                uint8_t* dst_ab30,
1050                int dst_stride_ab30,
1051                int width,
1052                int height) {
1053   return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1054                           src_stride_u, dst_ab30, dst_stride_ab30,
1055                           &kYvuH709Constants, width, height);
1056 }
1057 
1058 // Convert U010 to AB30.
1059 LIBYUV_API
U010ToAB30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)1060 int U010ToAB30(const uint16_t* src_y,
1061                int src_stride_y,
1062                const uint16_t* src_u,
1063                int src_stride_u,
1064                const uint16_t* src_v,
1065                int src_stride_v,
1066                uint8_t* dst_ab30,
1067                int dst_stride_ab30,
1068                int width,
1069                int height) {
1070   return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1071                           src_stride_u, dst_ab30, dst_stride_ab30,
1072                           &kYuv2020Constants, width, height);
1073 }
1074 
1075 // Convert 12 bit YUV to ARGB with matrix.
1076 // TODO(fbarchard): Consider passing scale multiplier to I212ToARGB to
1077 // multiply 12 bit yuv into high bits to allow any number of bits.
1078 LIBYUV_API
I012ToAR30Matrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height)1079 int I012ToAR30Matrix(const uint16_t* src_y,
1080                      int src_stride_y,
1081                      const uint16_t* src_u,
1082                      int src_stride_u,
1083                      const uint16_t* src_v,
1084                      int src_stride_v,
1085                      uint8_t* dst_ar30,
1086                      int dst_stride_ar30,
1087                      const struct YuvConstants* yuvconstants,
1088                      int width,
1089                      int height) {
1090   int y;
1091   void (*I212ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
1092                         const uint16_t* v_buf, uint8_t* rgb_buf,
1093                         const struct YuvConstants* yuvconstants, int width) =
1094       I212ToAR30Row_C;
1095   assert(yuvconstants);
1096   if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
1097     return -1;
1098   }
1099   // Negative height means invert the image.
1100   if (height < 0) {
1101     height = -height;
1102     dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
1103     dst_stride_ar30 = -dst_stride_ar30;
1104   }
1105 #if defined(HAS_I212TOAR30ROW_SSSE3)
1106   if (TestCpuFlag(kCpuHasSSSE3)) {
1107     I212ToAR30Row = I212ToAR30Row_Any_SSSE3;
1108     if (IS_ALIGNED(width, 8)) {
1109       I212ToAR30Row = I212ToAR30Row_SSSE3;
1110     }
1111   }
1112 #endif
1113 #if defined(HAS_I212TOAR30ROW_AVX2)
1114   if (TestCpuFlag(kCpuHasAVX2)) {
1115     I212ToAR30Row = I212ToAR30Row_Any_AVX2;
1116     if (IS_ALIGNED(width, 16)) {
1117       I212ToAR30Row = I212ToAR30Row_AVX2;
1118     }
1119   }
1120 #endif
1121   for (y = 0; y < height; ++y) {
1122     I212ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
1123     dst_ar30 += dst_stride_ar30;
1124     src_y += src_stride_y;
1125     if (y & 1) {
1126       src_u += src_stride_u;
1127       src_v += src_stride_v;
1128     }
1129   }
1130   return 0;
1131 }
1132 
1133 // Convert 10 bit YUV to ARGB with matrix.
1134 // TODO(fbarchard): Consider passing scale multiplier to I210ToARGB to
1135 // multiply 10 bit yuv into high bits to allow any number of bits.
1136 LIBYUV_API
I210ToAR30Matrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height)1137 int I210ToAR30Matrix(const uint16_t* src_y,
1138                      int src_stride_y,
1139                      const uint16_t* src_u,
1140                      int src_stride_u,
1141                      const uint16_t* src_v,
1142                      int src_stride_v,
1143                      uint8_t* dst_ar30,
1144                      int dst_stride_ar30,
1145                      const struct YuvConstants* yuvconstants,
1146                      int width,
1147                      int height) {
1148   int y;
1149   void (*I210ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
1150                         const uint16_t* v_buf, uint8_t* rgb_buf,
1151                         const struct YuvConstants* yuvconstants, int width) =
1152       I210ToAR30Row_C;
1153   assert(yuvconstants);
1154   if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
1155     return -1;
1156   }
1157   // Negative height means invert the image.
1158   if (height < 0) {
1159     height = -height;
1160     dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
1161     dst_stride_ar30 = -dst_stride_ar30;
1162   }
1163 #if defined(HAS_I210TOAR30ROW_SSSE3)
1164   if (TestCpuFlag(kCpuHasSSSE3)) {
1165     I210ToAR30Row = I210ToAR30Row_Any_SSSE3;
1166     if (IS_ALIGNED(width, 8)) {
1167       I210ToAR30Row = I210ToAR30Row_SSSE3;
1168     }
1169   }
1170 #endif
1171 #if defined(HAS_I210TOAR30ROW_AVX2)
1172   if (TestCpuFlag(kCpuHasAVX2)) {
1173     I210ToAR30Row = I210ToAR30Row_Any_AVX2;
1174     if (IS_ALIGNED(width, 16)) {
1175       I210ToAR30Row = I210ToAR30Row_AVX2;
1176     }
1177   }
1178 #endif
1179   for (y = 0; y < height; ++y) {
1180     I210ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
1181     dst_ar30 += dst_stride_ar30;
1182     src_y += src_stride_y;
1183     src_u += src_stride_u;
1184     src_v += src_stride_v;
1185   }
1186   return 0;
1187 }
1188 
1189 // Convert I210 to AR30.
1190 LIBYUV_API
I210ToAR30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,int width,int height)1191 int I210ToAR30(const uint16_t* src_y,
1192                int src_stride_y,
1193                const uint16_t* src_u,
1194                int src_stride_u,
1195                const uint16_t* src_v,
1196                int src_stride_v,
1197                uint8_t* dst_ar30,
1198                int dst_stride_ar30,
1199                int width,
1200                int height) {
1201   return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1202                           src_stride_v, dst_ar30, dst_stride_ar30,
1203                           &kYuvI601Constants, width, height);
1204 }
1205 
1206 // Convert H210 to AR30.
1207 LIBYUV_API
H210ToAR30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,int width,int height)1208 int H210ToAR30(const uint16_t* src_y,
1209                int src_stride_y,
1210                const uint16_t* src_u,
1211                int src_stride_u,
1212                const uint16_t* src_v,
1213                int src_stride_v,
1214                uint8_t* dst_ar30,
1215                int dst_stride_ar30,
1216                int width,
1217                int height) {
1218   return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1219                           src_stride_v, dst_ar30, dst_stride_ar30,
1220                           &kYuvH709Constants, width, height);
1221 }
1222 
1223 // Convert U210 to AR30.
1224 LIBYUV_API
U210ToAR30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,int width,int height)1225 int U210ToAR30(const uint16_t* src_y,
1226                int src_stride_y,
1227                const uint16_t* src_u,
1228                int src_stride_u,
1229                const uint16_t* src_v,
1230                int src_stride_v,
1231                uint8_t* dst_ar30,
1232                int dst_stride_ar30,
1233                int width,
1234                int height) {
1235   return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1236                           src_stride_v, dst_ar30, dst_stride_ar30,
1237                           &kYuv2020Constants, width, height);
1238 }
1239 
1240 // Convert I210 to AB30.
1241 LIBYUV_API
I210ToAB30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)1242 int I210ToAB30(const uint16_t* src_y,
1243                int src_stride_y,
1244                const uint16_t* src_u,
1245                int src_stride_u,
1246                const uint16_t* src_v,
1247                int src_stride_v,
1248                uint8_t* dst_ab30,
1249                int dst_stride_ab30,
1250                int width,
1251                int height) {
1252   return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1253                           src_stride_u, dst_ab30, dst_stride_ab30,
1254                           &kYvuI601Constants, width, height);
1255 }
1256 
1257 // Convert H210 to AB30.
1258 LIBYUV_API
H210ToAB30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)1259 int H210ToAB30(const uint16_t* src_y,
1260                int src_stride_y,
1261                const uint16_t* src_u,
1262                int src_stride_u,
1263                const uint16_t* src_v,
1264                int src_stride_v,
1265                uint8_t* dst_ab30,
1266                int dst_stride_ab30,
1267                int width,
1268                int height) {
1269   return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1270                           src_stride_u, dst_ab30, dst_stride_ab30,
1271                           &kYvuH709Constants, width, height);
1272 }
1273 
1274 // Convert U210 to AB30.
1275 LIBYUV_API
U210ToAB30(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)1276 int U210ToAB30(const uint16_t* src_y,
1277                int src_stride_y,
1278                const uint16_t* src_u,
1279                int src_stride_u,
1280                const uint16_t* src_v,
1281                int src_stride_v,
1282                uint8_t* dst_ab30,
1283                int dst_stride_ab30,
1284                int width,
1285                int height) {
1286   return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1287                           src_stride_u, dst_ab30, dst_stride_ab30,
1288                           &kYuv2020Constants, width, height);
1289 }
1290 
1291 LIBYUV_API
I410ToAR30Matrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height)1292 int I410ToAR30Matrix(const uint16_t* src_y,
1293                      int src_stride_y,
1294                      const uint16_t* src_u,
1295                      int src_stride_u,
1296                      const uint16_t* src_v,
1297                      int src_stride_v,
1298                      uint8_t* dst_ar30,
1299                      int dst_stride_ar30,
1300                      const struct YuvConstants* yuvconstants,
1301                      int width,
1302                      int height) {
1303   int y;
1304   void (*I410ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
1305                         const uint16_t* v_buf, uint8_t* rgb_buf,
1306                         const struct YuvConstants* yuvconstants, int width) =
1307       I410ToAR30Row_C;
1308   assert(yuvconstants);
1309   if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
1310     return -1;
1311   }
1312   // Negative height means invert the image.
1313   if (height < 0) {
1314     height = -height;
1315     dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
1316     dst_stride_ar30 = -dst_stride_ar30;
1317   }
1318 #if defined(HAS_I410TOAR30ROW_SSSE3)
1319   if (TestCpuFlag(kCpuHasSSSE3)) {
1320     I410ToAR30Row = I410ToAR30Row_Any_SSSE3;
1321     if (IS_ALIGNED(width, 8)) {
1322       I410ToAR30Row = I410ToAR30Row_SSSE3;
1323     }
1324   }
1325 #endif
1326 #if defined(HAS_I410TOAR30ROW_AVX2)
1327   if (TestCpuFlag(kCpuHasAVX2)) {
1328     I410ToAR30Row = I410ToAR30Row_Any_AVX2;
1329     if (IS_ALIGNED(width, 16)) {
1330       I410ToAR30Row = I410ToAR30Row_AVX2;
1331     }
1332   }
1333 #endif
1334   for (y = 0; y < height; ++y) {
1335     I410ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
1336     dst_ar30 += dst_stride_ar30;
1337     src_y += src_stride_y;
1338     src_u += src_stride_u;
1339     src_v += src_stride_v;
1340   }
1341   return 0;
1342 }
1343 
1344 // Convert 10 bit YUV to ARGB with matrix.
1345 LIBYUV_API
I010ToARGBMatrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)1346 int I010ToARGBMatrix(const uint16_t* src_y,
1347                      int src_stride_y,
1348                      const uint16_t* src_u,
1349                      int src_stride_u,
1350                      const uint16_t* src_v,
1351                      int src_stride_v,
1352                      uint8_t* dst_argb,
1353                      int dst_stride_argb,
1354                      const struct YuvConstants* yuvconstants,
1355                      int width,
1356                      int height) {
1357   int y;
1358   void (*I210ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
1359                         const uint16_t* v_buf, uint8_t* rgb_buf,
1360                         const struct YuvConstants* yuvconstants, int width) =
1361       I210ToARGBRow_C;
1362   assert(yuvconstants);
1363   if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
1364     return -1;
1365   }
1366   // Negative height means invert the image.
1367   if (height < 0) {
1368     height = -height;
1369     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1370     dst_stride_argb = -dst_stride_argb;
1371   }
1372 #if defined(HAS_I210TOARGBROW_SSSE3)
1373   if (TestCpuFlag(kCpuHasSSSE3)) {
1374     I210ToARGBRow = I210ToARGBRow_Any_SSSE3;
1375     if (IS_ALIGNED(width, 8)) {
1376       I210ToARGBRow = I210ToARGBRow_SSSE3;
1377     }
1378   }
1379 #endif
1380 #if defined(HAS_I210TOARGBROW_AVX2)
1381   if (TestCpuFlag(kCpuHasAVX2)) {
1382     I210ToARGBRow = I210ToARGBRow_Any_AVX2;
1383     if (IS_ALIGNED(width, 16)) {
1384       I210ToARGBRow = I210ToARGBRow_AVX2;
1385     }
1386   }
1387 #endif
1388   for (y = 0; y < height; ++y) {
1389     I210ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
1390     dst_argb += dst_stride_argb;
1391     src_y += src_stride_y;
1392     if (y & 1) {
1393       src_u += src_stride_u;
1394       src_v += src_stride_v;
1395     }
1396   }
1397   return 0;
1398 }
1399 
1400 // Convert I010 to ARGB.
1401 LIBYUV_API
I010ToARGB(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1402 int I010ToARGB(const uint16_t* src_y,
1403                int src_stride_y,
1404                const uint16_t* src_u,
1405                int src_stride_u,
1406                const uint16_t* src_v,
1407                int src_stride_v,
1408                uint8_t* dst_argb,
1409                int dst_stride_argb,
1410                int width,
1411                int height) {
1412   return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1413                           src_stride_v, dst_argb, dst_stride_argb,
1414                           &kYuvI601Constants, width, height);
1415 }
1416 
1417 // Convert I010 to ABGR.
1418 LIBYUV_API
I010ToABGR(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)1419 int I010ToABGR(const uint16_t* src_y,
1420                int src_stride_y,
1421                const uint16_t* src_u,
1422                int src_stride_u,
1423                const uint16_t* src_v,
1424                int src_stride_v,
1425                uint8_t* dst_abgr,
1426                int dst_stride_abgr,
1427                int width,
1428                int height) {
1429   return I010ToARGBMatrix(src_y, src_stride_y, src_v,
1430                           src_stride_v,  // Swap U and V
1431                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1432                           &kYvuI601Constants,  // Use Yvu matrix
1433                           width, height);
1434 }
1435 
1436 // Convert H010 to ARGB.
1437 LIBYUV_API
H010ToARGB(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1438 int H010ToARGB(const uint16_t* src_y,
1439                int src_stride_y,
1440                const uint16_t* src_u,
1441                int src_stride_u,
1442                const uint16_t* src_v,
1443                int src_stride_v,
1444                uint8_t* dst_argb,
1445                int dst_stride_argb,
1446                int width,
1447                int height) {
1448   return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1449                           src_stride_v, dst_argb, dst_stride_argb,
1450                           &kYuvH709Constants, width, height);
1451 }
1452 
1453 // Convert H010 to ABGR.
1454 LIBYUV_API
H010ToABGR(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)1455 int H010ToABGR(const uint16_t* src_y,
1456                int src_stride_y,
1457                const uint16_t* src_u,
1458                int src_stride_u,
1459                const uint16_t* src_v,
1460                int src_stride_v,
1461                uint8_t* dst_abgr,
1462                int dst_stride_abgr,
1463                int width,
1464                int height) {
1465   return I010ToARGBMatrix(src_y, src_stride_y, src_v,
1466                           src_stride_v,  // Swap U and V
1467                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1468                           &kYvuH709Constants,  // Use Yvu matrix
1469                           width, height);
1470 }
1471 
1472 // Convert U010 to ARGB.
1473 LIBYUV_API
U010ToARGB(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1474 int U010ToARGB(const uint16_t* src_y,
1475                int src_stride_y,
1476                const uint16_t* src_u,
1477                int src_stride_u,
1478                const uint16_t* src_v,
1479                int src_stride_v,
1480                uint8_t* dst_argb,
1481                int dst_stride_argb,
1482                int width,
1483                int height) {
1484   return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1485                           src_stride_v, dst_argb, dst_stride_argb,
1486                           &kYuv2020Constants, width, height);
1487 }
1488 
1489 // Convert U010 to ABGR.
1490 LIBYUV_API
U010ToABGR(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)1491 int U010ToABGR(const uint16_t* src_y,
1492                int src_stride_y,
1493                const uint16_t* src_u,
1494                int src_stride_u,
1495                const uint16_t* src_v,
1496                int src_stride_v,
1497                uint8_t* dst_abgr,
1498                int dst_stride_abgr,
1499                int width,
1500                int height) {
1501   return I010ToARGBMatrix(src_y, src_stride_y, src_v,
1502                           src_stride_v,  // Swap U and V
1503                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1504                           &kYvu2020Constants,  // Use Yvu matrix
1505                           width, height);
1506 }
1507 
1508 // Convert 12 bit YUV to ARGB with matrix.
1509 LIBYUV_API
I012ToARGBMatrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)1510 int I012ToARGBMatrix(const uint16_t* src_y,
1511                      int src_stride_y,
1512                      const uint16_t* src_u,
1513                      int src_stride_u,
1514                      const uint16_t* src_v,
1515                      int src_stride_v,
1516                      uint8_t* dst_argb,
1517                      int dst_stride_argb,
1518                      const struct YuvConstants* yuvconstants,
1519                      int width,
1520                      int height) {
1521   int y;
1522   void (*I212ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
1523                         const uint16_t* v_buf, uint8_t* rgb_buf,
1524                         const struct YuvConstants* yuvconstants, int width) =
1525       I212ToARGBRow_C;
1526   assert(yuvconstants);
1527   if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
1528     return -1;
1529   }
1530   // Negative height means invert the image.
1531   if (height < 0) {
1532     height = -height;
1533     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1534     dst_stride_argb = -dst_stride_argb;
1535   }
1536 #if defined(HAS_I212TOARGBROW_SSSE3)
1537   if (TestCpuFlag(kCpuHasSSSE3)) {
1538     I212ToARGBRow = I212ToARGBRow_Any_SSSE3;
1539     if (IS_ALIGNED(width, 8)) {
1540       I212ToARGBRow = I212ToARGBRow_SSSE3;
1541     }
1542   }
1543 #endif
1544 #if defined(HAS_I212TOARGBROW_AVX2)
1545   if (TestCpuFlag(kCpuHasAVX2)) {
1546     I212ToARGBRow = I212ToARGBRow_Any_AVX2;
1547     if (IS_ALIGNED(width, 16)) {
1548       I212ToARGBRow = I212ToARGBRow_AVX2;
1549     }
1550   }
1551 #endif
1552   for (y = 0; y < height; ++y) {
1553     I212ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
1554     dst_argb += dst_stride_argb;
1555     src_y += src_stride_y;
1556     if (y & 1) {
1557       src_u += src_stride_u;
1558       src_v += src_stride_v;
1559     }
1560   }
1561   return 0;
1562 }
1563 
1564 // Convert 10 bit 422 YUV to ARGB with matrix.
1565 LIBYUV_API
I210ToARGBMatrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)1566 int I210ToARGBMatrix(const uint16_t* src_y,
1567                      int src_stride_y,
1568                      const uint16_t* src_u,
1569                      int src_stride_u,
1570                      const uint16_t* src_v,
1571                      int src_stride_v,
1572                      uint8_t* dst_argb,
1573                      int dst_stride_argb,
1574                      const struct YuvConstants* yuvconstants,
1575                      int width,
1576                      int height) {
1577   int y;
1578   void (*I210ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
1579                         const uint16_t* v_buf, uint8_t* rgb_buf,
1580                         const struct YuvConstants* yuvconstants, int width) =
1581       I210ToARGBRow_C;
1582   assert(yuvconstants);
1583   if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
1584     return -1;
1585   }
1586   // Negative height means invert the image.
1587   if (height < 0) {
1588     height = -height;
1589     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1590     dst_stride_argb = -dst_stride_argb;
1591   }
1592 #if defined(HAS_I210TOARGBROW_SSSE3)
1593   if (TestCpuFlag(kCpuHasSSSE3)) {
1594     I210ToARGBRow = I210ToARGBRow_Any_SSSE3;
1595     if (IS_ALIGNED(width, 8)) {
1596       I210ToARGBRow = I210ToARGBRow_SSSE3;
1597     }
1598   }
1599 #endif
1600 #if defined(HAS_I210TOARGBROW_AVX2)
1601   if (TestCpuFlag(kCpuHasAVX2)) {
1602     I210ToARGBRow = I210ToARGBRow_Any_AVX2;
1603     if (IS_ALIGNED(width, 16)) {
1604       I210ToARGBRow = I210ToARGBRow_AVX2;
1605     }
1606   }
1607 #endif
1608   for (y = 0; y < height; ++y) {
1609     I210ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
1610     dst_argb += dst_stride_argb;
1611     src_y += src_stride_y;
1612     src_u += src_stride_u;
1613     src_v += src_stride_v;
1614   }
1615   return 0;
1616 }
1617 
1618 // Convert I210 to ARGB.
1619 LIBYUV_API
I210ToARGB(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1620 int I210ToARGB(const uint16_t* src_y,
1621                int src_stride_y,
1622                const uint16_t* src_u,
1623                int src_stride_u,
1624                const uint16_t* src_v,
1625                int src_stride_v,
1626                uint8_t* dst_argb,
1627                int dst_stride_argb,
1628                int width,
1629                int height) {
1630   return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1631                           src_stride_v, dst_argb, dst_stride_argb,
1632                           &kYuvI601Constants, width, height);
1633 }
1634 
1635 // Convert I210 to ABGR.
1636 LIBYUV_API
I210ToABGR(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)1637 int I210ToABGR(const uint16_t* src_y,
1638                int src_stride_y,
1639                const uint16_t* src_u,
1640                int src_stride_u,
1641                const uint16_t* src_v,
1642                int src_stride_v,
1643                uint8_t* dst_abgr,
1644                int dst_stride_abgr,
1645                int width,
1646                int height) {
1647   return I210ToARGBMatrix(src_y, src_stride_y, src_v,
1648                           src_stride_v,  // Swap U and V
1649                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1650                           &kYvuI601Constants,  // Use Yvu matrix
1651                           width, height);
1652 }
1653 
1654 // Convert H210 to ARGB.
1655 LIBYUV_API
H210ToARGB(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1656 int H210ToARGB(const uint16_t* src_y,
1657                int src_stride_y,
1658                const uint16_t* src_u,
1659                int src_stride_u,
1660                const uint16_t* src_v,
1661                int src_stride_v,
1662                uint8_t* dst_argb,
1663                int dst_stride_argb,
1664                int width,
1665                int height) {
1666   return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1667                           src_stride_v, dst_argb, dst_stride_argb,
1668                           &kYuvH709Constants, width, height);
1669 }
1670 
1671 // Convert H210 to ABGR.
1672 LIBYUV_API
H210ToABGR(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)1673 int H210ToABGR(const uint16_t* src_y,
1674                int src_stride_y,
1675                const uint16_t* src_u,
1676                int src_stride_u,
1677                const uint16_t* src_v,
1678                int src_stride_v,
1679                uint8_t* dst_abgr,
1680                int dst_stride_abgr,
1681                int width,
1682                int height) {
1683   return I210ToARGBMatrix(src_y, src_stride_y, src_v,
1684                           src_stride_v,  // Swap U and V
1685                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1686                           &kYvuH709Constants,  // Use Yvu matrix
1687                           width, height);
1688 }
1689 
1690 // Convert U210 to ARGB.
1691 LIBYUV_API
U210ToARGB(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1692 int U210ToARGB(const uint16_t* src_y,
1693                int src_stride_y,
1694                const uint16_t* src_u,
1695                int src_stride_u,
1696                const uint16_t* src_v,
1697                int src_stride_v,
1698                uint8_t* dst_argb,
1699                int dst_stride_argb,
1700                int width,
1701                int height) {
1702   return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1703                           src_stride_v, dst_argb, dst_stride_argb,
1704                           &kYuv2020Constants, width, height);
1705 }
1706 
1707 // Convert U210 to ABGR.
1708 LIBYUV_API
U210ToABGR(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)1709 int U210ToABGR(const uint16_t* src_y,
1710                int src_stride_y,
1711                const uint16_t* src_u,
1712                int src_stride_u,
1713                const uint16_t* src_v,
1714                int src_stride_v,
1715                uint8_t* dst_abgr,
1716                int dst_stride_abgr,
1717                int width,
1718                int height) {
1719   return I210ToARGBMatrix(src_y, src_stride_y, src_v,
1720                           src_stride_v,  // Swap U and V
1721                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1722                           &kYvu2020Constants,  // Use Yvu matrix
1723                           width, height);
1724 }
1725 
1726 LIBYUV_API
I410ToARGBMatrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)1727 int I410ToARGBMatrix(const uint16_t* src_y,
1728                      int src_stride_y,
1729                      const uint16_t* src_u,
1730                      int src_stride_u,
1731                      const uint16_t* src_v,
1732                      int src_stride_v,
1733                      uint8_t* dst_argb,
1734                      int dst_stride_argb,
1735                      const struct YuvConstants* yuvconstants,
1736                      int width,
1737                      int height) {
1738   int y;
1739   void (*I410ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
1740                         const uint16_t* v_buf, uint8_t* rgb_buf,
1741                         const struct YuvConstants* yuvconstants, int width) =
1742       I410ToARGBRow_C;
1743   assert(yuvconstants);
1744   if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
1745     return -1;
1746   }
1747   // Negative height means invert the image.
1748   if (height < 0) {
1749     height = -height;
1750     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1751     dst_stride_argb = -dst_stride_argb;
1752   }
1753 #if defined(HAS_I410TOARGBROW_SSSE3)
1754   if (TestCpuFlag(kCpuHasSSSE3)) {
1755     I410ToARGBRow = I410ToARGBRow_Any_SSSE3;
1756     if (IS_ALIGNED(width, 8)) {
1757       I410ToARGBRow = I410ToARGBRow_SSSE3;
1758     }
1759   }
1760 #endif
1761 #if defined(HAS_I410TOARGBROW_AVX2)
1762   if (TestCpuFlag(kCpuHasAVX2)) {
1763     I410ToARGBRow = I410ToARGBRow_Any_AVX2;
1764     if (IS_ALIGNED(width, 16)) {
1765       I410ToARGBRow = I410ToARGBRow_AVX2;
1766     }
1767   }
1768 #endif
1769   for (y = 0; y < height; ++y) {
1770     I410ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
1771     dst_argb += dst_stride_argb;
1772     src_y += src_stride_y;
1773     src_u += src_stride_u;
1774     src_v += src_stride_v;
1775   }
1776   return 0;
1777 }
1778 
1779 LIBYUV_API
P010ToARGBMatrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)1780 int P010ToARGBMatrix(const uint16_t* src_y,
1781                      int src_stride_y,
1782                      const uint16_t* src_uv,
1783                      int src_stride_uv,
1784                      uint8_t* dst_argb,
1785                      int dst_stride_argb,
1786                      const struct YuvConstants* yuvconstants,
1787                      int width,
1788                      int height) {
1789   int y;
1790   void (*P210ToARGBRow)(
1791       const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
1792       const struct YuvConstants* yuvconstants, int width) = P210ToARGBRow_C;
1793   assert(yuvconstants);
1794   if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
1795     return -1;
1796   }
1797   // Negative height means invert the image.
1798   if (height < 0) {
1799     height = -height;
1800     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1801     dst_stride_argb = -dst_stride_argb;
1802   }
1803 #if defined(HAS_P210TOARGBROW_SSSE3)
1804   if (TestCpuFlag(kCpuHasSSSE3)) {
1805     P210ToARGBRow = P210ToARGBRow_Any_SSSE3;
1806     if (IS_ALIGNED(width, 8)) {
1807       P210ToARGBRow = P210ToARGBRow_SSSE3;
1808     }
1809   }
1810 #endif
1811 #if defined(HAS_P210TOARGBROW_AVX2)
1812   if (TestCpuFlag(kCpuHasAVX2)) {
1813     P210ToARGBRow = P210ToARGBRow_Any_AVX2;
1814     if (IS_ALIGNED(width, 16)) {
1815       P210ToARGBRow = P210ToARGBRow_AVX2;
1816     }
1817   }
1818 #endif
1819   for (y = 0; y < height; ++y) {
1820     P210ToARGBRow(src_y, src_uv, dst_argb, yuvconstants, width);
1821     dst_argb += dst_stride_argb;
1822     src_y += src_stride_y;
1823     if (y & 1) {
1824       src_uv += src_stride_uv;
1825     }
1826   }
1827   return 0;
1828 }
1829 
1830 LIBYUV_API
P210ToARGBMatrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)1831 int P210ToARGBMatrix(const uint16_t* src_y,
1832                      int src_stride_y,
1833                      const uint16_t* src_uv,
1834                      int src_stride_uv,
1835                      uint8_t* dst_argb,
1836                      int dst_stride_argb,
1837                      const struct YuvConstants* yuvconstants,
1838                      int width,
1839                      int height) {
1840   int y;
1841   void (*P210ToARGBRow)(
1842       const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
1843       const struct YuvConstants* yuvconstants, int width) = P210ToARGBRow_C;
1844   assert(yuvconstants);
1845   if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
1846     return -1;
1847   }
1848   // Negative height means invert the image.
1849   if (height < 0) {
1850     height = -height;
1851     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1852     dst_stride_argb = -dst_stride_argb;
1853   }
1854 #if defined(HAS_P210TOARGBROW_SSSE3)
1855   if (TestCpuFlag(kCpuHasSSSE3)) {
1856     P210ToARGBRow = P210ToARGBRow_Any_SSSE3;
1857     if (IS_ALIGNED(width, 8)) {
1858       P210ToARGBRow = P210ToARGBRow_SSSE3;
1859     }
1860   }
1861 #endif
1862 #if defined(HAS_P210TOARGBROW_AVX2)
1863   if (TestCpuFlag(kCpuHasAVX2)) {
1864     P210ToARGBRow = P210ToARGBRow_Any_AVX2;
1865     if (IS_ALIGNED(width, 16)) {
1866       P210ToARGBRow = P210ToARGBRow_AVX2;
1867     }
1868   }
1869 #endif
1870   for (y = 0; y < height; ++y) {
1871     P210ToARGBRow(src_y, src_uv, dst_argb, yuvconstants, width);
1872     dst_argb += dst_stride_argb;
1873     src_y += src_stride_y;
1874     src_uv += src_stride_uv;
1875   }
1876   return 0;
1877 }
1878 
1879 LIBYUV_API
P010ToAR30Matrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height)1880 int P010ToAR30Matrix(const uint16_t* src_y,
1881                      int src_stride_y,
1882                      const uint16_t* src_uv,
1883                      int src_stride_uv,
1884                      uint8_t* dst_ar30,
1885                      int dst_stride_ar30,
1886                      const struct YuvConstants* yuvconstants,
1887                      int width,
1888                      int height) {
1889   int y;
1890   void (*P210ToAR30Row)(
1891       const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
1892       const struct YuvConstants* yuvconstants, int width) = P210ToAR30Row_C;
1893   assert(yuvconstants);
1894   if (!src_y || !src_uv || !dst_ar30 || width <= 0 || height == 0) {
1895     return -1;
1896   }
1897   // Negative height means invert the image.
1898   if (height < 0) {
1899     height = -height;
1900     dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
1901     dst_stride_ar30 = -dst_stride_ar30;
1902   }
1903 #if defined(HAS_P210TOAR30ROW_SSSE3)
1904   if (TestCpuFlag(kCpuHasSSSE3)) {
1905     P210ToAR30Row = P210ToAR30Row_Any_SSSE3;
1906     if (IS_ALIGNED(width, 8)) {
1907       P210ToAR30Row = P210ToAR30Row_SSSE3;
1908     }
1909   }
1910 #endif
1911 #if defined(HAS_P210TOAR30ROW_AVX2)
1912   if (TestCpuFlag(kCpuHasAVX2)) {
1913     P210ToAR30Row = P210ToAR30Row_Any_AVX2;
1914     if (IS_ALIGNED(width, 16)) {
1915       P210ToAR30Row = P210ToAR30Row_AVX2;
1916     }
1917   }
1918 #endif
1919   for (y = 0; y < height; ++y) {
1920     P210ToAR30Row(src_y, src_uv, dst_ar30, yuvconstants, width);
1921     dst_ar30 += dst_stride_ar30;
1922     src_y += src_stride_y;
1923     if (y & 1) {
1924       src_uv += src_stride_uv;
1925     }
1926   }
1927   return 0;
1928 }
1929 
1930 LIBYUV_API
P210ToAR30Matrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height)1931 int P210ToAR30Matrix(const uint16_t* src_y,
1932                      int src_stride_y,
1933                      const uint16_t* src_uv,
1934                      int src_stride_uv,
1935                      uint8_t* dst_ar30,
1936                      int dst_stride_ar30,
1937                      const struct YuvConstants* yuvconstants,
1938                      int width,
1939                      int height) {
1940   int y;
1941   void (*P210ToAR30Row)(
1942       const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
1943       const struct YuvConstants* yuvconstants, int width) = P210ToAR30Row_C;
1944   assert(yuvconstants);
1945   if (!src_y || !src_uv || !dst_ar30 || width <= 0 || height == 0) {
1946     return -1;
1947   }
1948   // Negative height means invert the image.
1949   if (height < 0) {
1950     height = -height;
1951     dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
1952     dst_stride_ar30 = -dst_stride_ar30;
1953   }
1954 #if defined(HAS_P210TOAR30ROW_SSSE3)
1955   if (TestCpuFlag(kCpuHasSSSE3)) {
1956     P210ToAR30Row = P210ToAR30Row_Any_SSSE3;
1957     if (IS_ALIGNED(width, 8)) {
1958       P210ToAR30Row = P210ToAR30Row_SSSE3;
1959     }
1960   }
1961 #endif
1962 #if defined(HAS_P210TOAR30ROW_AVX2)
1963   if (TestCpuFlag(kCpuHasAVX2)) {
1964     P210ToAR30Row = P210ToAR30Row_Any_AVX2;
1965     if (IS_ALIGNED(width, 16)) {
1966       P210ToAR30Row = P210ToAR30Row_AVX2;
1967     }
1968   }
1969 #endif
1970   for (y = 0; y < height; ++y) {
1971     P210ToAR30Row(src_y, src_uv, dst_ar30, yuvconstants, width);
1972     dst_ar30 += dst_stride_ar30;
1973     src_y += src_stride_y;
1974     src_uv += src_stride_uv;
1975   }
1976   return 0;
1977 }
1978 
1979 // Convert I420 with Alpha to preattenuated ARGB with matrix.
1980 LIBYUV_API
I420AlphaToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,const uint8_t * src_a,int src_stride_a,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,int attenuate)1981 int I420AlphaToARGBMatrix(const uint8_t* src_y,
1982                           int src_stride_y,
1983                           const uint8_t* src_u,
1984                           int src_stride_u,
1985                           const uint8_t* src_v,
1986                           int src_stride_v,
1987                           const uint8_t* src_a,
1988                           int src_stride_a,
1989                           uint8_t* dst_argb,
1990                           int dst_stride_argb,
1991                           const struct YuvConstants* yuvconstants,
1992                           int width,
1993                           int height,
1994                           int attenuate) {
1995   int y;
1996   void (*I422AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
1997                              const uint8_t* v_buf, const uint8_t* a_buf,
1998                              uint8_t* dst_argb,
1999                              const struct YuvConstants* yuvconstants,
2000                              int width) = I422AlphaToARGBRow_C;
2001   void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
2002                            int width) = ARGBAttenuateRow_C;
2003   assert(yuvconstants);
2004   if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
2005       height == 0) {
2006     return -1;
2007   }
2008   // Negative height means invert the image.
2009   if (height < 0) {
2010     height = -height;
2011     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2012     dst_stride_argb = -dst_stride_argb;
2013   }
2014 #if defined(HAS_I422ALPHATOARGBROW_SSSE3)
2015   if (TestCpuFlag(kCpuHasSSSE3)) {
2016     I422AlphaToARGBRow = I422AlphaToARGBRow_Any_SSSE3;
2017     if (IS_ALIGNED(width, 8)) {
2018       I422AlphaToARGBRow = I422AlphaToARGBRow_SSSE3;
2019     }
2020   }
2021 #endif
2022 #if defined(HAS_I422ALPHATOARGBROW_AVX2)
2023   if (TestCpuFlag(kCpuHasAVX2)) {
2024     I422AlphaToARGBRow = I422AlphaToARGBRow_Any_AVX2;
2025     if (IS_ALIGNED(width, 16)) {
2026       I422AlphaToARGBRow = I422AlphaToARGBRow_AVX2;
2027     }
2028   }
2029 #endif
2030 #if defined(HAS_I422ALPHATOARGBROW_NEON)
2031   if (TestCpuFlag(kCpuHasNEON)) {
2032     I422AlphaToARGBRow = I422AlphaToARGBRow_Any_NEON;
2033     if (IS_ALIGNED(width, 8)) {
2034       I422AlphaToARGBRow = I422AlphaToARGBRow_NEON;
2035     }
2036   }
2037 #endif
2038 #if defined(HAS_I422ALPHATOARGBROW_MSA)
2039   if (TestCpuFlag(kCpuHasMSA)) {
2040     I422AlphaToARGBRow = I422AlphaToARGBRow_Any_MSA;
2041     if (IS_ALIGNED(width, 8)) {
2042       I422AlphaToARGBRow = I422AlphaToARGBRow_MSA;
2043     }
2044   }
2045 #endif
2046 #if defined(HAS_I422ALPHATOARGBROW_LSX)
2047   if (TestCpuFlag(kCpuHasLSX)) {
2048     I422AlphaToARGBRow = I422AlphaToARGBRow_Any_LSX;
2049     if (IS_ALIGNED(width, 16)) {
2050       I422AlphaToARGBRow = I422AlphaToARGBRow_LSX;
2051     }
2052   }
2053 #endif
2054 #if defined(HAS_I422ALPHATOARGBROW_LASX)
2055   if (TestCpuFlag(kCpuHasLASX)) {
2056     I422AlphaToARGBRow = I422AlphaToARGBRow_Any_LASX;
2057     if (IS_ALIGNED(width, 16)) {
2058       I422AlphaToARGBRow = I422AlphaToARGBRow_LASX;
2059     }
2060   }
2061 #endif
2062 #if defined(HAS_I422ALPHATOARGBROW_RVV)
2063   if (TestCpuFlag(kCpuHasRVV)) {
2064     I422AlphaToARGBRow = I422AlphaToARGBRow_RVV;
2065   }
2066 #endif
2067 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
2068   if (TestCpuFlag(kCpuHasSSSE3)) {
2069     ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
2070     if (IS_ALIGNED(width, 4)) {
2071       ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
2072     }
2073   }
2074 #endif
2075 #if defined(HAS_ARGBATTENUATEROW_AVX2)
2076   if (TestCpuFlag(kCpuHasAVX2)) {
2077     ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
2078     if (IS_ALIGNED(width, 8)) {
2079       ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
2080     }
2081   }
2082 #endif
2083 #if defined(HAS_ARGBATTENUATEROW_NEON)
2084   if (TestCpuFlag(kCpuHasNEON)) {
2085     ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
2086     if (IS_ALIGNED(width, 8)) {
2087       ARGBAttenuateRow = ARGBAttenuateRow_NEON;
2088     }
2089   }
2090 #endif
2091 #if defined(HAS_ARGBATTENUATEROW_MSA)
2092   if (TestCpuFlag(kCpuHasMSA)) {
2093     ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
2094     if (IS_ALIGNED(width, 8)) {
2095       ARGBAttenuateRow = ARGBAttenuateRow_MSA;
2096     }
2097   }
2098 #endif
2099 #if defined(HAS_ARGBATTENUATEROW_RVV)
2100   if (TestCpuFlag(kCpuHasRVV)) {
2101     ARGBAttenuateRow = ARGBAttenuateRow_RVV;
2102   }
2103 #endif
2104 
2105   for (y = 0; y < height; ++y) {
2106     I422AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
2107                        width);
2108     if (attenuate) {
2109       ARGBAttenuateRow(dst_argb, dst_argb, width);
2110     }
2111     dst_argb += dst_stride_argb;
2112     src_a += src_stride_a;
2113     src_y += src_stride_y;
2114     if (y & 1) {
2115       src_u += src_stride_u;
2116       src_v += src_stride_v;
2117     }
2118   }
2119   return 0;
2120 }
2121 
2122 // Convert I422 with Alpha to preattenuated ARGB with matrix.
2123 LIBYUV_API
I422AlphaToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,const uint8_t * src_a,int src_stride_a,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,int attenuate)2124 int I422AlphaToARGBMatrix(const uint8_t* src_y,
2125                           int src_stride_y,
2126                           const uint8_t* src_u,
2127                           int src_stride_u,
2128                           const uint8_t* src_v,
2129                           int src_stride_v,
2130                           const uint8_t* src_a,
2131                           int src_stride_a,
2132                           uint8_t* dst_argb,
2133                           int dst_stride_argb,
2134                           const struct YuvConstants* yuvconstants,
2135                           int width,
2136                           int height,
2137                           int attenuate) {
2138   int y;
2139   void (*I422AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
2140                              const uint8_t* v_buf, const uint8_t* a_buf,
2141                              uint8_t* dst_argb,
2142                              const struct YuvConstants* yuvconstants,
2143                              int width) = I422AlphaToARGBRow_C;
2144   void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
2145                            int width) = ARGBAttenuateRow_C;
2146   assert(yuvconstants);
2147   if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
2148       height == 0) {
2149     return -1;
2150   }
2151   // Negative height means invert the image.
2152   if (height < 0) {
2153     height = -height;
2154     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2155     dst_stride_argb = -dst_stride_argb;
2156   }
2157 #if defined(HAS_I422ALPHATOARGBROW_SSSE3)
2158   if (TestCpuFlag(kCpuHasSSSE3)) {
2159     I422AlphaToARGBRow = I422AlphaToARGBRow_Any_SSSE3;
2160     if (IS_ALIGNED(width, 8)) {
2161       I422AlphaToARGBRow = I422AlphaToARGBRow_SSSE3;
2162     }
2163   }
2164 #endif
2165 #if defined(HAS_I422ALPHATOARGBROW_AVX2)
2166   if (TestCpuFlag(kCpuHasAVX2)) {
2167     I422AlphaToARGBRow = I422AlphaToARGBRow_Any_AVX2;
2168     if (IS_ALIGNED(width, 16)) {
2169       I422AlphaToARGBRow = I422AlphaToARGBRow_AVX2;
2170     }
2171   }
2172 #endif
2173 #if defined(HAS_I422ALPHATOARGBROW_NEON)
2174   if (TestCpuFlag(kCpuHasNEON)) {
2175     I422AlphaToARGBRow = I422AlphaToARGBRow_Any_NEON;
2176     if (IS_ALIGNED(width, 8)) {
2177       I422AlphaToARGBRow = I422AlphaToARGBRow_NEON;
2178     }
2179   }
2180 #endif
2181 #if defined(HAS_I422ALPHATOARGBROW_MSA)
2182   if (TestCpuFlag(kCpuHasMSA)) {
2183     I422AlphaToARGBRow = I422AlphaToARGBRow_Any_MSA;
2184     if (IS_ALIGNED(width, 8)) {
2185       I422AlphaToARGBRow = I422AlphaToARGBRow_MSA;
2186     }
2187   }
2188 #endif
2189 #if defined(HAS_I422ALPHATOARGBROW_LSX)
2190   if (TestCpuFlag(kCpuHasLSX)) {
2191     I422AlphaToARGBRow = I422AlphaToARGBRow_Any_LSX;
2192     if (IS_ALIGNED(width, 16)) {
2193       I422AlphaToARGBRow = I422AlphaToARGBRow_LSX;
2194     }
2195   }
2196 #endif
2197 #if defined(HAS_I422ALPHATOARGBROW_LASX)
2198   if (TestCpuFlag(kCpuHasLASX)) {
2199     I422AlphaToARGBRow = I422AlphaToARGBRow_Any_LASX;
2200     if (IS_ALIGNED(width, 16)) {
2201       I422AlphaToARGBRow = I422AlphaToARGBRow_LASX;
2202     }
2203   }
2204 #endif
2205 #if defined(HAS_I422ALPHATOARGBROW_RVV)
2206   if (TestCpuFlag(kCpuHasRVV)) {
2207     I422AlphaToARGBRow = I422AlphaToARGBRow_RVV;
2208   }
2209 #endif
2210 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
2211   if (TestCpuFlag(kCpuHasSSSE3)) {
2212     ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
2213     if (IS_ALIGNED(width, 4)) {
2214       ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
2215     }
2216   }
2217 #endif
2218 #if defined(HAS_ARGBATTENUATEROW_AVX2)
2219   if (TestCpuFlag(kCpuHasAVX2)) {
2220     ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
2221     if (IS_ALIGNED(width, 8)) {
2222       ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
2223     }
2224   }
2225 #endif
2226 #if defined(HAS_ARGBATTENUATEROW_NEON)
2227   if (TestCpuFlag(kCpuHasNEON)) {
2228     ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
2229     if (IS_ALIGNED(width, 8)) {
2230       ARGBAttenuateRow = ARGBAttenuateRow_NEON;
2231     }
2232   }
2233 #endif
2234 #if defined(HAS_ARGBATTENUATEROW_MSA)
2235   if (TestCpuFlag(kCpuHasMSA)) {
2236     ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
2237     if (IS_ALIGNED(width, 8)) {
2238       ARGBAttenuateRow = ARGBAttenuateRow_MSA;
2239     }
2240   }
2241 #endif
2242 #if defined(HAS_ARGBATTENUATEROW_RVV)
2243   if (TestCpuFlag(kCpuHasRVV)) {
2244     ARGBAttenuateRow = ARGBAttenuateRow_RVV;
2245   }
2246 #endif
2247 
2248   for (y = 0; y < height; ++y) {
2249     I422AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
2250                        width);
2251     if (attenuate) {
2252       ARGBAttenuateRow(dst_argb, dst_argb, width);
2253     }
2254     dst_argb += dst_stride_argb;
2255     src_a += src_stride_a;
2256     src_y += src_stride_y;
2257     src_u += src_stride_u;
2258     src_v += src_stride_v;
2259   }
2260   return 0;
2261 }
2262 
2263 // Convert I444 with Alpha to preattenuated ARGB with matrix.
2264 LIBYUV_API
I444AlphaToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,const uint8_t * src_a,int src_stride_a,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,int attenuate)2265 int I444AlphaToARGBMatrix(const uint8_t* src_y,
2266                           int src_stride_y,
2267                           const uint8_t* src_u,
2268                           int src_stride_u,
2269                           const uint8_t* src_v,
2270                           int src_stride_v,
2271                           const uint8_t* src_a,
2272                           int src_stride_a,
2273                           uint8_t* dst_argb,
2274                           int dst_stride_argb,
2275                           const struct YuvConstants* yuvconstants,
2276                           int width,
2277                           int height,
2278                           int attenuate) {
2279   int y;
2280   void (*I444AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
2281                              const uint8_t* v_buf, const uint8_t* a_buf,
2282                              uint8_t* dst_argb,
2283                              const struct YuvConstants* yuvconstants,
2284                              int width) = I444AlphaToARGBRow_C;
2285   void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
2286                            int width) = ARGBAttenuateRow_C;
2287   assert(yuvconstants);
2288   if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
2289       height == 0) {
2290     return -1;
2291   }
2292   // Negative height means invert the image.
2293   if (height < 0) {
2294     height = -height;
2295     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2296     dst_stride_argb = -dst_stride_argb;
2297   }
2298 #if defined(HAS_I444ALPHATOARGBROW_SSSE3)
2299   if (TestCpuFlag(kCpuHasSSSE3)) {
2300     I444AlphaToARGBRow = I444AlphaToARGBRow_Any_SSSE3;
2301     if (IS_ALIGNED(width, 8)) {
2302       I444AlphaToARGBRow = I444AlphaToARGBRow_SSSE3;
2303     }
2304   }
2305 #endif
2306 #if defined(HAS_I444ALPHATOARGBROW_AVX2)
2307   if (TestCpuFlag(kCpuHasAVX2)) {
2308     I444AlphaToARGBRow = I444AlphaToARGBRow_Any_AVX2;
2309     if (IS_ALIGNED(width, 16)) {
2310       I444AlphaToARGBRow = I444AlphaToARGBRow_AVX2;
2311     }
2312   }
2313 #endif
2314 #if defined(HAS_I444ALPHATOARGBROW_NEON)
2315   if (TestCpuFlag(kCpuHasNEON)) {
2316     I444AlphaToARGBRow = I444AlphaToARGBRow_Any_NEON;
2317     if (IS_ALIGNED(width, 8)) {
2318       I444AlphaToARGBRow = I444AlphaToARGBRow_NEON;
2319     }
2320   }
2321 #endif
2322 #if defined(HAS_I444ALPHATOARGBROW_MSA)
2323   if (TestCpuFlag(kCpuHasMSA)) {
2324     I444AlphaToARGBRow = I444AlphaToARGBRow_Any_MSA;
2325     if (IS_ALIGNED(width, 8)) {
2326       I444AlphaToARGBRow = I444AlphaToARGBRow_MSA;
2327     }
2328   }
2329 #endif
2330 #if defined(HAS_I444ALPHATOARGBROW_RVV)
2331   if (TestCpuFlag(kCpuHasRVV)) {
2332     I444AlphaToARGBRow = I444AlphaToARGBRow_RVV;
2333   }
2334 #endif
2335 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
2336   if (TestCpuFlag(kCpuHasSSSE3)) {
2337     ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
2338     if (IS_ALIGNED(width, 4)) {
2339       ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
2340     }
2341   }
2342 #endif
2343 #if defined(HAS_ARGBATTENUATEROW_AVX2)
2344   if (TestCpuFlag(kCpuHasAVX2)) {
2345     ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
2346     if (IS_ALIGNED(width, 8)) {
2347       ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
2348     }
2349   }
2350 #endif
2351 #if defined(HAS_ARGBATTENUATEROW_NEON)
2352   if (TestCpuFlag(kCpuHasNEON)) {
2353     ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
2354     if (IS_ALIGNED(width, 8)) {
2355       ARGBAttenuateRow = ARGBAttenuateRow_NEON;
2356     }
2357   }
2358 #endif
2359 #if defined(HAS_ARGBATTENUATEROW_MSA)
2360   if (TestCpuFlag(kCpuHasMSA)) {
2361     ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
2362     if (IS_ALIGNED(width, 8)) {
2363       ARGBAttenuateRow = ARGBAttenuateRow_MSA;
2364     }
2365   }
2366 #endif
2367 #if defined(HAS_ARGBATTENUATEROW_RVV)
2368   if (TestCpuFlag(kCpuHasRVV)) {
2369     ARGBAttenuateRow = ARGBAttenuateRow_RVV;
2370   }
2371 #endif
2372 
2373   for (y = 0; y < height; ++y) {
2374     I444AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
2375                        width);
2376     if (attenuate) {
2377       ARGBAttenuateRow(dst_argb, dst_argb, width);
2378     }
2379     dst_argb += dst_stride_argb;
2380     src_a += src_stride_a;
2381     src_y += src_stride_y;
2382     src_u += src_stride_u;
2383     src_v += src_stride_v;
2384   }
2385   return 0;
2386 }
2387 
2388 // Convert I420 with Alpha to ARGB.
2389 LIBYUV_API
I420AlphaToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,const uint8_t * src_a,int src_stride_a,uint8_t * dst_argb,int dst_stride_argb,int width,int height,int attenuate)2390 int I420AlphaToARGB(const uint8_t* src_y,
2391                     int src_stride_y,
2392                     const uint8_t* src_u,
2393                     int src_stride_u,
2394                     const uint8_t* src_v,
2395                     int src_stride_v,
2396                     const uint8_t* src_a,
2397                     int src_stride_a,
2398                     uint8_t* dst_argb,
2399                     int dst_stride_argb,
2400                     int width,
2401                     int height,
2402                     int attenuate) {
2403   return I420AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
2404                                src_stride_v, src_a, src_stride_a, dst_argb,
2405                                dst_stride_argb, &kYuvI601Constants, width,
2406                                height, attenuate);
2407 }
2408 
2409 // Convert I420 with Alpha to ABGR.
2410 LIBYUV_API
I420AlphaToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,const uint8_t * src_a,int src_stride_a,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height,int attenuate)2411 int I420AlphaToABGR(const uint8_t* src_y,
2412                     int src_stride_y,
2413                     const uint8_t* src_u,
2414                     int src_stride_u,
2415                     const uint8_t* src_v,
2416                     int src_stride_v,
2417                     const uint8_t* src_a,
2418                     int src_stride_a,
2419                     uint8_t* dst_abgr,
2420                     int dst_stride_abgr,
2421                     int width,
2422                     int height,
2423                     int attenuate) {
2424   return I420AlphaToARGBMatrix(
2425       src_y, src_stride_y, src_v, src_stride_v,  // Swap U and V
2426       src_u, src_stride_u, src_a, src_stride_a, dst_abgr, dst_stride_abgr,
2427       &kYvuI601Constants,  // Use Yvu matrix
2428       width, height, attenuate);
2429 }
2430 
2431 // Convert I422 with Alpha to ARGB.
2432 LIBYUV_API
I422AlphaToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,const uint8_t * src_a,int src_stride_a,uint8_t * dst_argb,int dst_stride_argb,int width,int height,int attenuate)2433 int I422AlphaToARGB(const uint8_t* src_y,
2434                     int src_stride_y,
2435                     const uint8_t* src_u,
2436                     int src_stride_u,
2437                     const uint8_t* src_v,
2438                     int src_stride_v,
2439                     const uint8_t* src_a,
2440                     int src_stride_a,
2441                     uint8_t* dst_argb,
2442                     int dst_stride_argb,
2443                     int width,
2444                     int height,
2445                     int attenuate) {
2446   return I422AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
2447                                src_stride_v, src_a, src_stride_a, dst_argb,
2448                                dst_stride_argb, &kYuvI601Constants, width,
2449                                height, attenuate);
2450 }
2451 
2452 // Convert I422 with Alpha to ABGR.
2453 LIBYUV_API
I422AlphaToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,const uint8_t * src_a,int src_stride_a,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height,int attenuate)2454 int I422AlphaToABGR(const uint8_t* src_y,
2455                     int src_stride_y,
2456                     const uint8_t* src_u,
2457                     int src_stride_u,
2458                     const uint8_t* src_v,
2459                     int src_stride_v,
2460                     const uint8_t* src_a,
2461                     int src_stride_a,
2462                     uint8_t* dst_abgr,
2463                     int dst_stride_abgr,
2464                     int width,
2465                     int height,
2466                     int attenuate) {
2467   return I422AlphaToARGBMatrix(
2468       src_y, src_stride_y, src_v, src_stride_v,  // Swap U and V
2469       src_u, src_stride_u, src_a, src_stride_a, dst_abgr, dst_stride_abgr,
2470       &kYvuI601Constants,  // Use Yvu matrix
2471       width, height, attenuate);
2472 }
2473 
2474 // Convert I444 with Alpha to ARGB.
2475 LIBYUV_API
I444AlphaToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,const uint8_t * src_a,int src_stride_a,uint8_t * dst_argb,int dst_stride_argb,int width,int height,int attenuate)2476 int I444AlphaToARGB(const uint8_t* src_y,
2477                     int src_stride_y,
2478                     const uint8_t* src_u,
2479                     int src_stride_u,
2480                     const uint8_t* src_v,
2481                     int src_stride_v,
2482                     const uint8_t* src_a,
2483                     int src_stride_a,
2484                     uint8_t* dst_argb,
2485                     int dst_stride_argb,
2486                     int width,
2487                     int height,
2488                     int attenuate) {
2489   return I444AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
2490                                src_stride_v, src_a, src_stride_a, dst_argb,
2491                                dst_stride_argb, &kYuvI601Constants, width,
2492                                height, attenuate);
2493 }
2494 
2495 // Convert I444 with Alpha to ABGR.
2496 LIBYUV_API
I444AlphaToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,const uint8_t * src_a,int src_stride_a,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height,int attenuate)2497 int I444AlphaToABGR(const uint8_t* src_y,
2498                     int src_stride_y,
2499                     const uint8_t* src_u,
2500                     int src_stride_u,
2501                     const uint8_t* src_v,
2502                     int src_stride_v,
2503                     const uint8_t* src_a,
2504                     int src_stride_a,
2505                     uint8_t* dst_abgr,
2506                     int dst_stride_abgr,
2507                     int width,
2508                     int height,
2509                     int attenuate) {
2510   return I444AlphaToARGBMatrix(
2511       src_y, src_stride_y, src_v, src_stride_v,  // Swap U and V
2512       src_u, src_stride_u, src_a, src_stride_a, dst_abgr, dst_stride_abgr,
2513       &kYvuI601Constants,  // Use Yvu matrix
2514       width, height, attenuate);
2515 }
2516 
2517 // Convert I010 with Alpha to preattenuated ARGB with matrix.
2518 LIBYUV_API
I010AlphaToARGBMatrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,const uint16_t * src_a,int src_stride_a,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,int attenuate)2519 int I010AlphaToARGBMatrix(const uint16_t* src_y,
2520                           int src_stride_y,
2521                           const uint16_t* src_u,
2522                           int src_stride_u,
2523                           const uint16_t* src_v,
2524                           int src_stride_v,
2525                           const uint16_t* src_a,
2526                           int src_stride_a,
2527                           uint8_t* dst_argb,
2528                           int dst_stride_argb,
2529                           const struct YuvConstants* yuvconstants,
2530                           int width,
2531                           int height,
2532                           int attenuate) {
2533   int y;
2534   void (*I210AlphaToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
2535                              const uint16_t* v_buf, const uint16_t* a_buf,
2536                              uint8_t* dst_argb,
2537                              const struct YuvConstants* yuvconstants,
2538                              int width) = I210AlphaToARGBRow_C;
2539   void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
2540                            int width) = ARGBAttenuateRow_C;
2541   assert(yuvconstants);
2542   if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
2543       height == 0) {
2544     return -1;
2545   }
2546   // Negative height means invert the image.
2547   if (height < 0) {
2548     height = -height;
2549     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2550     dst_stride_argb = -dst_stride_argb;
2551   }
2552 #if defined(HAS_I210ALPHATOARGBROW_SSSE3)
2553   if (TestCpuFlag(kCpuHasSSSE3)) {
2554     I210AlphaToARGBRow = I210AlphaToARGBRow_Any_SSSE3;
2555     if (IS_ALIGNED(width, 8)) {
2556       I210AlphaToARGBRow = I210AlphaToARGBRow_SSSE3;
2557     }
2558   }
2559 #endif
2560 #if defined(HAS_I210ALPHATOARGBROW_AVX2)
2561   if (TestCpuFlag(kCpuHasAVX2)) {
2562     I210AlphaToARGBRow = I210AlphaToARGBRow_Any_AVX2;
2563     if (IS_ALIGNED(width, 16)) {
2564       I210AlphaToARGBRow = I210AlphaToARGBRow_AVX2;
2565     }
2566   }
2567 #endif
2568 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
2569   if (TestCpuFlag(kCpuHasSSSE3)) {
2570     ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
2571     if (IS_ALIGNED(width, 4)) {
2572       ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
2573     }
2574   }
2575 #endif
2576 #if defined(HAS_ARGBATTENUATEROW_AVX2)
2577   if (TestCpuFlag(kCpuHasAVX2)) {
2578     ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
2579     if (IS_ALIGNED(width, 8)) {
2580       ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
2581     }
2582   }
2583 #endif
2584 #if defined(HAS_ARGBATTENUATEROW_NEON)
2585   if (TestCpuFlag(kCpuHasNEON)) {
2586     ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
2587     if (IS_ALIGNED(width, 8)) {
2588       ARGBAttenuateRow = ARGBAttenuateRow_NEON;
2589     }
2590   }
2591 #endif
2592 #if defined(HAS_ARGBATTENUATEROW_MSA)
2593   if (TestCpuFlag(kCpuHasMSA)) {
2594     ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
2595     if (IS_ALIGNED(width, 8)) {
2596       ARGBAttenuateRow = ARGBAttenuateRow_MSA;
2597     }
2598   }
2599 #endif
2600 #if defined(HAS_ARGBATTENUATEROW_RVV)
2601   if (TestCpuFlag(kCpuHasRVV)) {
2602     ARGBAttenuateRow = ARGBAttenuateRow_RVV;
2603   }
2604 #endif
2605 
2606   for (y = 0; y < height; ++y) {
2607     I210AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
2608                        width);
2609     if (attenuate) {
2610       ARGBAttenuateRow(dst_argb, dst_argb, width);
2611     }
2612     dst_argb += dst_stride_argb;
2613     src_a += src_stride_a;
2614     src_y += src_stride_y;
2615     if (y & 1) {
2616       src_u += src_stride_u;
2617       src_v += src_stride_v;
2618     }
2619   }
2620   return 0;
2621 }
2622 
2623 // Convert I210 with Alpha to preattenuated ARGB with matrix.
2624 LIBYUV_API
I210AlphaToARGBMatrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,const uint16_t * src_a,int src_stride_a,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,int attenuate)2625 int I210AlphaToARGBMatrix(const uint16_t* src_y,
2626                           int src_stride_y,
2627                           const uint16_t* src_u,
2628                           int src_stride_u,
2629                           const uint16_t* src_v,
2630                           int src_stride_v,
2631                           const uint16_t* src_a,
2632                           int src_stride_a,
2633                           uint8_t* dst_argb,
2634                           int dst_stride_argb,
2635                           const struct YuvConstants* yuvconstants,
2636                           int width,
2637                           int height,
2638                           int attenuate) {
2639   int y;
2640   void (*I210AlphaToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
2641                              const uint16_t* v_buf, const uint16_t* a_buf,
2642                              uint8_t* dst_argb,
2643                              const struct YuvConstants* yuvconstants,
2644                              int width) = I210AlphaToARGBRow_C;
2645   void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
2646                            int width) = ARGBAttenuateRow_C;
2647   assert(yuvconstants);
2648   if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
2649       height == 0) {
2650     return -1;
2651   }
2652   // Negative height means invert the image.
2653   if (height < 0) {
2654     height = -height;
2655     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2656     dst_stride_argb = -dst_stride_argb;
2657   }
2658 #if defined(HAS_I210ALPHATOARGBROW_SSSE3)
2659   if (TestCpuFlag(kCpuHasSSSE3)) {
2660     I210AlphaToARGBRow = I210AlphaToARGBRow_Any_SSSE3;
2661     if (IS_ALIGNED(width, 8)) {
2662       I210AlphaToARGBRow = I210AlphaToARGBRow_SSSE3;
2663     }
2664   }
2665 #endif
2666 #if defined(HAS_I210ALPHATOARGBROW_AVX2)
2667   if (TestCpuFlag(kCpuHasAVX2)) {
2668     I210AlphaToARGBRow = I210AlphaToARGBRow_Any_AVX2;
2669     if (IS_ALIGNED(width, 16)) {
2670       I210AlphaToARGBRow = I210AlphaToARGBRow_AVX2;
2671     }
2672   }
2673 #endif
2674 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
2675   if (TestCpuFlag(kCpuHasSSSE3)) {
2676     ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
2677     if (IS_ALIGNED(width, 4)) {
2678       ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
2679     }
2680   }
2681 #endif
2682 #if defined(HAS_ARGBATTENUATEROW_AVX2)
2683   if (TestCpuFlag(kCpuHasAVX2)) {
2684     ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
2685     if (IS_ALIGNED(width, 8)) {
2686       ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
2687     }
2688   }
2689 #endif
2690 #if defined(HAS_ARGBATTENUATEROW_NEON)
2691   if (TestCpuFlag(kCpuHasNEON)) {
2692     ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
2693     if (IS_ALIGNED(width, 8)) {
2694       ARGBAttenuateRow = ARGBAttenuateRow_NEON;
2695     }
2696   }
2697 #endif
2698 #if defined(HAS_ARGBATTENUATEROW_MSA)
2699   if (TestCpuFlag(kCpuHasMSA)) {
2700     ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
2701     if (IS_ALIGNED(width, 8)) {
2702       ARGBAttenuateRow = ARGBAttenuateRow_MSA;
2703     }
2704   }
2705 #endif
2706 #if defined(HAS_ARGBATTENUATEROW_RVV)
2707   if (TestCpuFlag(kCpuHasRVV)) {
2708     ARGBAttenuateRow = ARGBAttenuateRow_RVV;
2709   }
2710 #endif
2711 
2712   for (y = 0; y < height; ++y) {
2713     I210AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
2714                        width);
2715     if (attenuate) {
2716       ARGBAttenuateRow(dst_argb, dst_argb, width);
2717     }
2718     dst_argb += dst_stride_argb;
2719     src_a += src_stride_a;
2720     src_y += src_stride_y;
2721     src_u += src_stride_u;
2722     src_v += src_stride_v;
2723   }
2724   return 0;
2725 }
2726 
2727 // Convert I410 with Alpha to preattenuated ARGB with matrix.
2728 LIBYUV_API
I410AlphaToARGBMatrix(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,const uint16_t * src_a,int src_stride_a,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,int attenuate)2729 int I410AlphaToARGBMatrix(const uint16_t* src_y,
2730                           int src_stride_y,
2731                           const uint16_t* src_u,
2732                           int src_stride_u,
2733                           const uint16_t* src_v,
2734                           int src_stride_v,
2735                           const uint16_t* src_a,
2736                           int src_stride_a,
2737                           uint8_t* dst_argb,
2738                           int dst_stride_argb,
2739                           const struct YuvConstants* yuvconstants,
2740                           int width,
2741                           int height,
2742                           int attenuate) {
2743   int y;
2744   void (*I410AlphaToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
2745                              const uint16_t* v_buf, const uint16_t* a_buf,
2746                              uint8_t* dst_argb,
2747                              const struct YuvConstants* yuvconstants,
2748                              int width) = I410AlphaToARGBRow_C;
2749   void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
2750                            int width) = ARGBAttenuateRow_C;
2751   assert(yuvconstants);
2752   if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
2753       height == 0) {
2754     return -1;
2755   }
2756   // Negative height means invert the image.
2757   if (height < 0) {
2758     height = -height;
2759     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2760     dst_stride_argb = -dst_stride_argb;
2761   }
2762 #if defined(HAS_I410ALPHATOARGBROW_SSSE3)
2763   if (TestCpuFlag(kCpuHasSSSE3)) {
2764     I410AlphaToARGBRow = I410AlphaToARGBRow_Any_SSSE3;
2765     if (IS_ALIGNED(width, 8)) {
2766       I410AlphaToARGBRow = I410AlphaToARGBRow_SSSE3;
2767     }
2768   }
2769 #endif
2770 #if defined(HAS_I410ALPHATOARGBROW_AVX2)
2771   if (TestCpuFlag(kCpuHasAVX2)) {
2772     I410AlphaToARGBRow = I410AlphaToARGBRow_Any_AVX2;
2773     if (IS_ALIGNED(width, 16)) {
2774       I410AlphaToARGBRow = I410AlphaToARGBRow_AVX2;
2775     }
2776   }
2777 #endif
2778 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
2779   if (TestCpuFlag(kCpuHasSSSE3)) {
2780     ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
2781     if (IS_ALIGNED(width, 4)) {
2782       ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
2783     }
2784   }
2785 #endif
2786 #if defined(HAS_ARGBATTENUATEROW_AVX2)
2787   if (TestCpuFlag(kCpuHasAVX2)) {
2788     ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
2789     if (IS_ALIGNED(width, 8)) {
2790       ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
2791     }
2792   }
2793 #endif
2794 #if defined(HAS_ARGBATTENUATEROW_NEON)
2795   if (TestCpuFlag(kCpuHasNEON)) {
2796     ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
2797     if (IS_ALIGNED(width, 8)) {
2798       ARGBAttenuateRow = ARGBAttenuateRow_NEON;
2799     }
2800   }
2801 #endif
2802 #if defined(HAS_ARGBATTENUATEROW_MSA)
2803   if (TestCpuFlag(kCpuHasMSA)) {
2804     ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
2805     if (IS_ALIGNED(width, 8)) {
2806       ARGBAttenuateRow = ARGBAttenuateRow_MSA;
2807     }
2808   }
2809 #endif
2810 #if defined(HAS_ARGBATTENUATEROW_RVV)
2811   if (TestCpuFlag(kCpuHasRVV)) {
2812     ARGBAttenuateRow = ARGBAttenuateRow_RVV;
2813   }
2814 #endif
2815 
2816   for (y = 0; y < height; ++y) {
2817     I410AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
2818                        width);
2819     if (attenuate) {
2820       ARGBAttenuateRow(dst_argb, dst_argb, width);
2821     }
2822     dst_argb += dst_stride_argb;
2823     src_a += src_stride_a;
2824     src_y += src_stride_y;
2825     src_u += src_stride_u;
2826     src_v += src_stride_v;
2827   }
2828   return 0;
2829 }
2830 
2831 // Convert I400 to ARGB with matrix.
2832 LIBYUV_API
I400ToARGBMatrix(const uint8_t * src_y,int src_stride_y,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)2833 int I400ToARGBMatrix(const uint8_t* src_y,
2834                      int src_stride_y,
2835                      uint8_t* dst_argb,
2836                      int dst_stride_argb,
2837                      const struct YuvConstants* yuvconstants,
2838                      int width,
2839                      int height) {
2840   int y;
2841   void (*I400ToARGBRow)(const uint8_t* y_buf, uint8_t* rgb_buf,
2842                         const struct YuvConstants* yuvconstants, int width) =
2843       I400ToARGBRow_C;
2844   assert(yuvconstants);
2845   if (!src_y || !dst_argb || width <= 0 || height == 0) {
2846     return -1;
2847   }
2848   // Negative height means invert the image.
2849   if (height < 0) {
2850     height = -height;
2851     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2852     dst_stride_argb = -dst_stride_argb;
2853   }
2854   // Coalesce rows.
2855   if (src_stride_y == width && dst_stride_argb == width * 4) {
2856     width *= height;
2857     height = 1;
2858     src_stride_y = dst_stride_argb = 0;
2859   }
2860 #if defined(HAS_I400TOARGBROW_SSE2)
2861   if (TestCpuFlag(kCpuHasSSE2)) {
2862     I400ToARGBRow = I400ToARGBRow_Any_SSE2;
2863     if (IS_ALIGNED(width, 8)) {
2864       I400ToARGBRow = I400ToARGBRow_SSE2;
2865     }
2866   }
2867 #endif
2868 #if defined(HAS_I400TOARGBROW_AVX2)
2869   if (TestCpuFlag(kCpuHasAVX2)) {
2870     I400ToARGBRow = I400ToARGBRow_Any_AVX2;
2871     if (IS_ALIGNED(width, 16)) {
2872       I400ToARGBRow = I400ToARGBRow_AVX2;
2873     }
2874   }
2875 #endif
2876 #if defined(HAS_I400TOARGBROW_NEON)
2877   if (TestCpuFlag(kCpuHasNEON)) {
2878     I400ToARGBRow = I400ToARGBRow_Any_NEON;
2879     if (IS_ALIGNED(width, 8)) {
2880       I400ToARGBRow = I400ToARGBRow_NEON;
2881     }
2882   }
2883 #endif
2884 #if defined(HAS_I400TOARGBROW_MSA)
2885   if (TestCpuFlag(kCpuHasMSA)) {
2886     I400ToARGBRow = I400ToARGBRow_Any_MSA;
2887     if (IS_ALIGNED(width, 16)) {
2888       I400ToARGBRow = I400ToARGBRow_MSA;
2889     }
2890   }
2891 #endif
2892 #if defined(HAS_I400TOARGBROW_LSX)
2893   if (TestCpuFlag(kCpuHasLSX)) {
2894     I400ToARGBRow = I400ToARGBRow_Any_LSX;
2895     if (IS_ALIGNED(width, 16)) {
2896       I400ToARGBRow = I400ToARGBRow_LSX;
2897     }
2898   }
2899 #endif
2900 #if defined(HAS_I400TOARGBROW_RVV)
2901   if (TestCpuFlag(kCpuHasRVV)) {
2902     I400ToARGBRow = I400ToARGBRow_RVV;
2903   }
2904 #endif
2905 
2906   for (y = 0; y < height; ++y) {
2907     I400ToARGBRow(src_y, dst_argb, yuvconstants, width);
2908     dst_argb += dst_stride_argb;
2909     src_y += src_stride_y;
2910   }
2911   return 0;
2912 }
2913 
2914 // Convert I400 to ARGB.
2915 LIBYUV_API
I400ToARGB(const uint8_t * src_y,int src_stride_y,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2916 int I400ToARGB(const uint8_t* src_y,
2917                int src_stride_y,
2918                uint8_t* dst_argb,
2919                int dst_stride_argb,
2920                int width,
2921                int height) {
2922   return I400ToARGBMatrix(src_y, src_stride_y, dst_argb, dst_stride_argb,
2923                           &kYuvI601Constants, width, height);
2924 }
2925 
2926 // Convert J400 to ARGB.
2927 LIBYUV_API
J400ToARGB(const uint8_t * src_y,int src_stride_y,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2928 int J400ToARGB(const uint8_t* src_y,
2929                int src_stride_y,
2930                uint8_t* dst_argb,
2931                int dst_stride_argb,
2932                int width,
2933                int height) {
2934   int y;
2935   void (*J400ToARGBRow)(const uint8_t* src_y, uint8_t* dst_argb, int width) =
2936       J400ToARGBRow_C;
2937   if (!src_y || !dst_argb || width <= 0 || height == 0) {
2938     return -1;
2939   }
2940   // Negative height means invert the image.
2941   if (height < 0) {
2942     height = -height;
2943     src_y = src_y + (height - 1) * src_stride_y;
2944     src_stride_y = -src_stride_y;
2945   }
2946   // Coalesce rows.
2947   if (src_stride_y == width && dst_stride_argb == width * 4) {
2948     width *= height;
2949     height = 1;
2950     src_stride_y = dst_stride_argb = 0;
2951   }
2952 #if defined(HAS_J400TOARGBROW_SSE2)
2953   if (TestCpuFlag(kCpuHasSSE2)) {
2954     J400ToARGBRow = J400ToARGBRow_Any_SSE2;
2955     if (IS_ALIGNED(width, 8)) {
2956       J400ToARGBRow = J400ToARGBRow_SSE2;
2957     }
2958   }
2959 #endif
2960 #if defined(HAS_J400TOARGBROW_AVX2)
2961   if (TestCpuFlag(kCpuHasAVX2)) {
2962     J400ToARGBRow = J400ToARGBRow_Any_AVX2;
2963     if (IS_ALIGNED(width, 16)) {
2964       J400ToARGBRow = J400ToARGBRow_AVX2;
2965     }
2966   }
2967 #endif
2968 #if defined(HAS_J400TOARGBROW_NEON)
2969   if (TestCpuFlag(kCpuHasNEON)) {
2970     J400ToARGBRow = J400ToARGBRow_Any_NEON;
2971     if (IS_ALIGNED(width, 8)) {
2972       J400ToARGBRow = J400ToARGBRow_NEON;
2973     }
2974   }
2975 #endif
2976 #if defined(HAS_J400TOARGBROW_MSA)
2977   if (TestCpuFlag(kCpuHasMSA)) {
2978     J400ToARGBRow = J400ToARGBRow_Any_MSA;
2979     if (IS_ALIGNED(width, 16)) {
2980       J400ToARGBRow = J400ToARGBRow_MSA;
2981     }
2982   }
2983 #endif
2984 #if defined(HAS_J400TOARGBROW_LSX)
2985   if (TestCpuFlag(kCpuHasLSX)) {
2986     J400ToARGBRow = J400ToARGBRow_Any_LSX;
2987     if (IS_ALIGNED(width, 16)) {
2988       J400ToARGBRow = J400ToARGBRow_LSX;
2989     }
2990   }
2991 #endif
2992 #if defined(HAS_J400TOARGBROW_RVV)
2993   if (TestCpuFlag(kCpuHasRVV)) {
2994     J400ToARGBRow = J400ToARGBRow_RVV;
2995   }
2996 #endif
2997 
2998   for (y = 0; y < height; ++y) {
2999     J400ToARGBRow(src_y, dst_argb, width);
3000     src_y += src_stride_y;
3001     dst_argb += dst_stride_argb;
3002   }
3003   return 0;
3004 }
3005 
3006 #ifndef __riscv
3007 // Shuffle table for converting BGRA to ARGB.
3008 static const uvec8 kShuffleMaskBGRAToARGB = {
3009     3u, 2u, 1u, 0u, 7u, 6u, 5u, 4u, 11u, 10u, 9u, 8u, 15u, 14u, 13u, 12u};
3010 
3011 // Shuffle table for converting ABGR to ARGB.
3012 static const uvec8 kShuffleMaskABGRToARGB = {
3013     2u, 1u, 0u, 3u, 6u, 5u, 4u, 7u, 10u, 9u, 8u, 11u, 14u, 13u, 12u, 15u};
3014 
3015 // Shuffle table for converting RGBA to ARGB.
3016 static const uvec8 kShuffleMaskRGBAToARGB = {
3017     1u, 2u, 3u, 0u, 5u, 6u, 7u, 4u, 9u, 10u, 11u, 8u, 13u, 14u, 15u, 12u};
3018 
3019 // Shuffle table for converting AR64 to AB64.
3020 static const uvec8 kShuffleMaskAR64ToAB64 = {
3021     4u, 5u, 2u, 3u, 0u, 1u, 6u, 7u, 12u, 13u, 10u, 11u, 8u, 9u, 14u, 15u};
3022 
3023 // Convert BGRA to ARGB.
3024 LIBYUV_API
BGRAToARGB(const uint8_t * src_bgra,int src_stride_bgra,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3025 int BGRAToARGB(const uint8_t* src_bgra,
3026                int src_stride_bgra,
3027                uint8_t* dst_argb,
3028                int dst_stride_argb,
3029                int width,
3030                int height) {
3031   return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb,
3032                      (const uint8_t*)&kShuffleMaskBGRAToARGB, width, height);
3033 }
3034 
3035 // Convert ARGB to BGRA (same as BGRAToARGB).
3036 LIBYUV_API
ARGBToBGRA(const uint8_t * src_bgra,int src_stride_bgra,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3037 int ARGBToBGRA(const uint8_t* src_bgra,
3038                int src_stride_bgra,
3039                uint8_t* dst_argb,
3040                int dst_stride_argb,
3041                int width,
3042                int height) {
3043   return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb,
3044                      (const uint8_t*)&kShuffleMaskBGRAToARGB, width, height);
3045 }
3046 
3047 // Convert ABGR to ARGB.
3048 LIBYUV_API
ABGRToARGB(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3049 int ABGRToARGB(const uint8_t* src_abgr,
3050                int src_stride_abgr,
3051                uint8_t* dst_argb,
3052                int dst_stride_argb,
3053                int width,
3054                int height) {
3055   return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb,
3056                      (const uint8_t*)&kShuffleMaskABGRToARGB, width, height);
3057 }
3058 
3059 // Convert ARGB to ABGR to (same as ABGRToARGB).
3060 LIBYUV_API
ARGBToABGR(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3061 int ARGBToABGR(const uint8_t* src_abgr,
3062                int src_stride_abgr,
3063                uint8_t* dst_argb,
3064                int dst_stride_argb,
3065                int width,
3066                int height) {
3067   return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb,
3068                      (const uint8_t*)&kShuffleMaskABGRToARGB, width, height);
3069 }
3070 
3071 // Convert RGBA to ARGB.
3072 LIBYUV_API
RGBAToARGB(const uint8_t * src_rgba,int src_stride_rgba,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3073 int RGBAToARGB(const uint8_t* src_rgba,
3074                int src_stride_rgba,
3075                uint8_t* dst_argb,
3076                int dst_stride_argb,
3077                int width,
3078                int height) {
3079   return ARGBShuffle(src_rgba, src_stride_rgba, dst_argb, dst_stride_argb,
3080                      (const uint8_t*)&kShuffleMaskRGBAToARGB, width, height);
3081 }
3082 
3083 // Convert AR64 To AB64.
3084 LIBYUV_API
AR64ToAB64(const uint16_t * src_ar64,int src_stride_ar64,uint16_t * dst_ab64,int dst_stride_ab64,int width,int height)3085 int AR64ToAB64(const uint16_t* src_ar64,
3086                int src_stride_ar64,
3087                uint16_t* dst_ab64,
3088                int dst_stride_ab64,
3089                int width,
3090                int height) {
3091   return AR64Shuffle(src_ar64, src_stride_ar64, dst_ab64, dst_stride_ab64,
3092                      (const uint8_t*)&kShuffleMaskAR64ToAB64, width, height);
3093 }
3094 #else
3095 // Convert BGRA to ARGB (same as ARGBToBGRA).
3096 LIBYUV_API
BGRAToARGB(const uint8_t * src_bgra,int src_stride_bgra,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3097 int BGRAToARGB(const uint8_t* src_bgra,
3098                int src_stride_bgra,
3099                uint8_t* dst_argb,
3100                int dst_stride_argb,
3101                int width,
3102                int height) {
3103   return ARGBToBGRA(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb, width,
3104                     height);
3105 }
3106 
3107 // Convert ARGB to BGRA.
3108 LIBYUV_API
ARGBToBGRA(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_bgra,int dst_stride_bgra,int width,int height)3109 int ARGBToBGRA(const uint8_t* src_argb,
3110                int src_stride_argb,
3111                uint8_t* dst_bgra,
3112                int dst_stride_bgra,
3113                int width,
3114                int height) {
3115   int y;
3116   void (*ARGBToBGRARow)(const uint8_t* src_argb, uint8_t* dst_bgra, int width) =
3117       ARGBToBGRARow_C;
3118   if (!src_argb || !dst_bgra || width <= 0 || height == 0) {
3119     return -1;
3120   }
3121   // Negative height means invert the image.
3122   if (height < 0) {
3123     height = -height;
3124     src_argb = src_argb + (height - 1) * src_stride_argb;
3125     src_stride_argb = -src_stride_argb;
3126   }
3127   // Coalesce rows.
3128   if (src_stride_argb == width * 4 && dst_stride_bgra == width * 4) {
3129     width *= height;
3130     height = 1;
3131     src_stride_argb = dst_stride_bgra = 0;
3132   }
3133 
3134 #if defined(HAS_ARGBTOBGRAROW_RVV)
3135   if (TestCpuFlag(kCpuHasRVV)) {
3136     ARGBToBGRARow = ARGBToBGRARow_RVV;
3137   }
3138 #endif
3139 
3140   for (y = 0; y < height; ++y) {
3141     ARGBToBGRARow(src_argb, dst_bgra, width);
3142     src_argb += src_stride_argb;
3143     dst_bgra += dst_stride_bgra;
3144   }
3145   return 0;
3146 }
3147 
3148 // Convert ARGB to ABGR.
3149 LIBYUV_API
ARGBToABGR(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)3150 int ARGBToABGR(const uint8_t* src_argb,
3151                int src_stride_argb,
3152                uint8_t* dst_abgr,
3153                int dst_stride_abgr,
3154                int width,
3155                int height) {
3156   int y;
3157   void (*ARGBToABGRRow)(const uint8_t* src_argb, uint8_t* dst_abgr, int width) =
3158       ARGBToABGRRow_C;
3159   if (!src_argb || !dst_abgr || width <= 0 || height == 0) {
3160     return -1;
3161   }
3162   // Negative height means invert the image.
3163   if (height < 0) {
3164     height = -height;
3165     src_argb = src_argb + (height - 1) * src_stride_argb;
3166     src_stride_argb = -src_stride_argb;
3167   }
3168   // Coalesce rows.
3169   if (src_stride_argb == width * 4 && dst_stride_abgr == width * 4) {
3170     width *= height;
3171     height = 1;
3172     src_stride_argb = dst_stride_abgr = 0;
3173   }
3174 
3175 #if defined(HAS_ARGBTOABGRROW_RVV)
3176   if (TestCpuFlag(kCpuHasRVV)) {
3177     ARGBToABGRRow = ARGBToABGRRow_RVV;
3178   }
3179 #endif
3180 
3181   for (y = 0; y < height; ++y) {
3182     ARGBToABGRRow(src_argb, dst_abgr, width);
3183     src_argb += src_stride_argb;
3184     dst_abgr += dst_stride_abgr;
3185   }
3186   return 0;
3187 }
3188 
3189 // Convert ABGR to ARGB (same as ARGBToABGR).
3190 LIBYUV_API
ABGRToARGB(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3191 int ABGRToARGB(const uint8_t* src_abgr,
3192                int src_stride_abgr,
3193                uint8_t* dst_argb,
3194                int dst_stride_argb,
3195                int width,
3196                int height) {
3197   return ARGBToABGR(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb, width,
3198                     height);
3199 }
3200 
3201 // Convert RGBA to ARGB.
3202 LIBYUV_API
RGBAToARGB(const uint8_t * src_rgba,int src_stride_rgba,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3203 int RGBAToARGB(const uint8_t* src_rgba,
3204                int src_stride_rgba,
3205                uint8_t* dst_argb,
3206                int dst_stride_argb,
3207                int width,
3208                int height) {
3209   int y;
3210   void (*RGBAToARGBRow)(const uint8_t* src_rgba, uint8_t* dst_argb, int width) =
3211       RGBAToARGBRow_C;
3212   if (!src_rgba || !dst_argb || width <= 0 || height == 0) {
3213     return -1;
3214   }
3215   // Negative height means invert the image.
3216   if (height < 0) {
3217     height = -height;
3218     src_rgba = src_rgba + (height - 1) * src_stride_rgba;
3219     src_stride_rgba = -src_stride_rgba;
3220   }
3221   // Coalesce rows.
3222   if (src_stride_rgba == width * 4 && dst_stride_argb == width * 4) {
3223     width *= height;
3224     height = 1;
3225     src_stride_rgba = dst_stride_argb = 0;
3226   }
3227 
3228 #if defined(HAS_RGBATOARGBROW_RVV)
3229   if (TestCpuFlag(kCpuHasRVV)) {
3230     RGBAToARGBRow = RGBAToARGBRow_RVV;
3231   }
3232 #endif
3233 
3234   for (y = 0; y < height; ++y) {
3235     RGBAToARGBRow(src_rgba, dst_argb, width);
3236     src_rgba += src_stride_rgba;
3237     dst_argb += dst_stride_argb;
3238   }
3239   return 0;
3240 }
3241 
3242 // Convert AR64 To AB64.
3243 LIBYUV_API
AR64ToAB64(const uint16_t * src_ar64,int src_stride_ar64,uint16_t * dst_ab64,int dst_stride_ab64,int width,int height)3244 int AR64ToAB64(const uint16_t* src_ar64,
3245                int src_stride_ar64,
3246                uint16_t* dst_ab64,
3247                int dst_stride_ab64,
3248                int width,
3249                int height) {
3250   int y;
3251   void (*AR64ToAB64Row)(const uint16_t* src_ar64, uint16_t* dst_ab64,
3252                         int width) = AR64ToAB64Row_C;
3253   if (!src_ar64 || !dst_ab64 || width <= 0 || height == 0) {
3254     return -1;
3255   }
3256   // Negative height means invert the image.
3257   if (height < 0) {
3258     height = -height;
3259     src_ar64 = src_ar64 + (height - 1) * src_stride_ar64;
3260     src_stride_ar64 = -src_stride_ar64;
3261   }
3262   // Coalesce rows.
3263   if (src_stride_ar64 == width * 4 && dst_stride_ab64 == width * 4) {
3264     width *= height;
3265     height = 1;
3266     src_stride_ar64 = dst_stride_ab64 = 0;
3267   }
3268 
3269 #if defined(HAS_AR64TOAB64ROW_RVV)
3270   if (TestCpuFlag(kCpuHasRVV)) {
3271     AR64ToAB64Row = AR64ToAB64Row_RVV;
3272   }
3273 #endif
3274 
3275   for (y = 0; y < height; ++y) {
3276     AR64ToAB64Row(src_ar64, dst_ab64, width);
3277     src_ar64 += src_stride_ar64;
3278     dst_ab64 += dst_stride_ab64;
3279   }
3280   return 0;
3281 }
3282 #endif
3283 
3284 // Convert RGB24 to ARGB.
3285 LIBYUV_API
RGB24ToARGB(const uint8_t * src_rgb24,int src_stride_rgb24,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3286 int RGB24ToARGB(const uint8_t* src_rgb24,
3287                 int src_stride_rgb24,
3288                 uint8_t* dst_argb,
3289                 int dst_stride_argb,
3290                 int width,
3291                 int height) {
3292   int y;
3293   void (*RGB24ToARGBRow)(const uint8_t* src_rgb, uint8_t* dst_argb, int width) =
3294       RGB24ToARGBRow_C;
3295   if (!src_rgb24 || !dst_argb || width <= 0 || height == 0) {
3296     return -1;
3297   }
3298   // Negative height means invert the image.
3299   if (height < 0) {
3300     height = -height;
3301     src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24;
3302     src_stride_rgb24 = -src_stride_rgb24;
3303   }
3304   // Coalesce rows.
3305   if (src_stride_rgb24 == width * 3 && dst_stride_argb == width * 4) {
3306     width *= height;
3307     height = 1;
3308     src_stride_rgb24 = dst_stride_argb = 0;
3309   }
3310 #if defined(HAS_RGB24TOARGBROW_SSSE3)
3311   if (TestCpuFlag(kCpuHasSSSE3)) {
3312     RGB24ToARGBRow = RGB24ToARGBRow_Any_SSSE3;
3313     if (IS_ALIGNED(width, 16)) {
3314       RGB24ToARGBRow = RGB24ToARGBRow_SSSE3;
3315     }
3316   }
3317 #endif
3318 #if defined(HAS_RGB24TOARGBROW_NEON)
3319   if (TestCpuFlag(kCpuHasNEON)) {
3320     RGB24ToARGBRow = RGB24ToARGBRow_Any_NEON;
3321     if (IS_ALIGNED(width, 8)) {
3322       RGB24ToARGBRow = RGB24ToARGBRow_NEON;
3323     }
3324   }
3325 #endif
3326 #if defined(HAS_RGB24TOARGBROW_MSA)
3327   if (TestCpuFlag(kCpuHasMSA)) {
3328     RGB24ToARGBRow = RGB24ToARGBRow_Any_MSA;
3329     if (IS_ALIGNED(width, 16)) {
3330       RGB24ToARGBRow = RGB24ToARGBRow_MSA;
3331     }
3332   }
3333 #endif
3334 #if defined(HAS_RGB24TOARGBROW_LSX)
3335   if (TestCpuFlag(kCpuHasLSX)) {
3336     RGB24ToARGBRow = RGB24ToARGBRow_Any_LSX;
3337     if (IS_ALIGNED(width, 16)) {
3338       RGB24ToARGBRow = RGB24ToARGBRow_LSX;
3339     }
3340   }
3341 #endif
3342 #if defined(HAS_RGB24TOARGBROW_LASX)
3343   if (TestCpuFlag(kCpuHasLASX)) {
3344     RGB24ToARGBRow = RGB24ToARGBRow_Any_LASX;
3345     if (IS_ALIGNED(width, 32)) {
3346       RGB24ToARGBRow = RGB24ToARGBRow_LASX;
3347     }
3348   }
3349 #endif
3350 #if defined(HAS_RGB24TOARGBROW_RVV)
3351   if (TestCpuFlag(kCpuHasRVV)) {
3352     RGB24ToARGBRow = RGB24ToARGBRow_RVV;
3353   }
3354 #endif
3355 
3356   for (y = 0; y < height; ++y) {
3357     RGB24ToARGBRow(src_rgb24, dst_argb, width);
3358     src_rgb24 += src_stride_rgb24;
3359     dst_argb += dst_stride_argb;
3360   }
3361   return 0;
3362 }
3363 
3364 // Convert RAW to ARGB.
3365 LIBYUV_API
RAWToARGB(const uint8_t * src_raw,int src_stride_raw,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3366 int RAWToARGB(const uint8_t* src_raw,
3367               int src_stride_raw,
3368               uint8_t* dst_argb,
3369               int dst_stride_argb,
3370               int width,
3371               int height) {
3372   int y;
3373   void (*RAWToARGBRow)(const uint8_t* src_rgb, uint8_t* dst_argb, int width) =
3374       RAWToARGBRow_C;
3375   if (!src_raw || !dst_argb || width <= 0 || height == 0) {
3376     return -1;
3377   }
3378   // Negative height means invert the image.
3379   if (height < 0) {
3380     height = -height;
3381     src_raw = src_raw + (height - 1) * src_stride_raw;
3382     src_stride_raw = -src_stride_raw;
3383   }
3384   // Coalesce rows.
3385   if (src_stride_raw == width * 3 && dst_stride_argb == width * 4) {
3386     width *= height;
3387     height = 1;
3388     src_stride_raw = dst_stride_argb = 0;
3389   }
3390 #if defined(HAS_RAWTOARGBROW_SSSE3)
3391   if (TestCpuFlag(kCpuHasSSSE3)) {
3392     RAWToARGBRow = RAWToARGBRow_Any_SSSE3;
3393     if (IS_ALIGNED(width, 16)) {
3394       RAWToARGBRow = RAWToARGBRow_SSSE3;
3395     }
3396   }
3397 #endif
3398 #if defined(HAS_RAWTOARGBROW_NEON)
3399   if (TestCpuFlag(kCpuHasNEON)) {
3400     RAWToARGBRow = RAWToARGBRow_Any_NEON;
3401     if (IS_ALIGNED(width, 8)) {
3402       RAWToARGBRow = RAWToARGBRow_NEON;
3403     }
3404   }
3405 #endif
3406 #if defined(HAS_RAWTOARGBROW_MSA)
3407   if (TestCpuFlag(kCpuHasMSA)) {
3408     RAWToARGBRow = RAWToARGBRow_Any_MSA;
3409     if (IS_ALIGNED(width, 16)) {
3410       RAWToARGBRow = RAWToARGBRow_MSA;
3411     }
3412   }
3413 #endif
3414 #if defined(HAS_RAWTOARGBROW_LSX)
3415   if (TestCpuFlag(kCpuHasLSX)) {
3416     RAWToARGBRow = RAWToARGBRow_Any_LSX;
3417     if (IS_ALIGNED(width, 16)) {
3418       RAWToARGBRow = RAWToARGBRow_LSX;
3419     }
3420   }
3421 #endif
3422 #if defined(HAS_RAWTOARGBROW_LASX)
3423   if (TestCpuFlag(kCpuHasLASX)) {
3424     RAWToARGBRow = RAWToARGBRow_Any_LASX;
3425     if (IS_ALIGNED(width, 32)) {
3426       RAWToARGBRow = RAWToARGBRow_LASX;
3427     }
3428   }
3429 #endif
3430 #if defined(HAS_RAWTOARGBROW_RVV)
3431   if (TestCpuFlag(kCpuHasRVV)) {
3432     RAWToARGBRow = RAWToARGBRow_RVV;
3433   }
3434 #endif
3435 
3436   for (y = 0; y < height; ++y) {
3437     RAWToARGBRow(src_raw, dst_argb, width);
3438     src_raw += src_stride_raw;
3439     dst_argb += dst_stride_argb;
3440   }
3441   return 0;
3442 }
3443 
3444 // Convert RAW to RGBA.
3445 LIBYUV_API
RAWToRGBA(const uint8_t * src_raw,int src_stride_raw,uint8_t * dst_rgba,int dst_stride_rgba,int width,int height)3446 int RAWToRGBA(const uint8_t* src_raw,
3447               int src_stride_raw,
3448               uint8_t* dst_rgba,
3449               int dst_stride_rgba,
3450               int width,
3451               int height) {
3452   int y;
3453   void (*RAWToRGBARow)(const uint8_t* src_rgb, uint8_t* dst_rgba, int width) =
3454       RAWToRGBARow_C;
3455   if (!src_raw || !dst_rgba || width <= 0 || height == 0) {
3456     return -1;
3457   }
3458   // Negative height means invert the image.
3459   if (height < 0) {
3460     height = -height;
3461     src_raw = src_raw + (height - 1) * src_stride_raw;
3462     src_stride_raw = -src_stride_raw;
3463   }
3464   // Coalesce rows.
3465   if (src_stride_raw == width * 3 && dst_stride_rgba == width * 4) {
3466     width *= height;
3467     height = 1;
3468     src_stride_raw = dst_stride_rgba = 0;
3469   }
3470 #if defined(HAS_RAWTORGBAROW_SSSE3)
3471   if (TestCpuFlag(kCpuHasSSSE3)) {
3472     RAWToRGBARow = RAWToRGBARow_Any_SSSE3;
3473     if (IS_ALIGNED(width, 16)) {
3474       RAWToRGBARow = RAWToRGBARow_SSSE3;
3475     }
3476   }
3477 #endif
3478 #if defined(HAS_RAWTORGBAROW_NEON)
3479   if (TestCpuFlag(kCpuHasNEON)) {
3480     RAWToRGBARow = RAWToRGBARow_Any_NEON;
3481     if (IS_ALIGNED(width, 8)) {
3482       RAWToRGBARow = RAWToRGBARow_NEON;
3483     }
3484   }
3485 #endif
3486 #if defined(HAS_RAWTORGBAROW_RVV)
3487   if (TestCpuFlag(kCpuHasRVV)) {
3488     RAWToRGBARow = RAWToRGBARow_RVV;
3489   }
3490 #endif
3491 
3492   for (y = 0; y < height; ++y) {
3493     RAWToRGBARow(src_raw, dst_rgba, width);
3494     src_raw += src_stride_raw;
3495     dst_rgba += dst_stride_rgba;
3496   }
3497   return 0;
3498 }
3499 
3500 // Convert RGB565 to ARGB.
3501 LIBYUV_API
RGB565ToARGB(const uint8_t * src_rgb565,int src_stride_rgb565,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3502 int RGB565ToARGB(const uint8_t* src_rgb565,
3503                  int src_stride_rgb565,
3504                  uint8_t* dst_argb,
3505                  int dst_stride_argb,
3506                  int width,
3507                  int height) {
3508   int y;
3509   void (*RGB565ToARGBRow)(const uint8_t* src_rgb565, uint8_t* dst_argb,
3510                           int width) = RGB565ToARGBRow_C;
3511   if (!src_rgb565 || !dst_argb || width <= 0 || height == 0) {
3512     return -1;
3513   }
3514   // Negative height means invert the image.
3515   if (height < 0) {
3516     height = -height;
3517     src_rgb565 = src_rgb565 + (height - 1) * src_stride_rgb565;
3518     src_stride_rgb565 = -src_stride_rgb565;
3519   }
3520   // Coalesce rows.
3521   if (src_stride_rgb565 == width * 2 && dst_stride_argb == width * 4) {
3522     width *= height;
3523     height = 1;
3524     src_stride_rgb565 = dst_stride_argb = 0;
3525   }
3526 #if defined(HAS_RGB565TOARGBROW_SSE2)
3527   if (TestCpuFlag(kCpuHasSSE2)) {
3528     RGB565ToARGBRow = RGB565ToARGBRow_Any_SSE2;
3529     if (IS_ALIGNED(width, 8)) {
3530       RGB565ToARGBRow = RGB565ToARGBRow_SSE2;
3531     }
3532   }
3533 #endif
3534 #if defined(HAS_RGB565TOARGBROW_AVX2)
3535   if (TestCpuFlag(kCpuHasAVX2)) {
3536     RGB565ToARGBRow = RGB565ToARGBRow_Any_AVX2;
3537     if (IS_ALIGNED(width, 16)) {
3538       RGB565ToARGBRow = RGB565ToARGBRow_AVX2;
3539     }
3540   }
3541 #endif
3542 #if defined(HAS_RGB565TOARGBROW_NEON)
3543   if (TestCpuFlag(kCpuHasNEON)) {
3544     RGB565ToARGBRow = RGB565ToARGBRow_Any_NEON;
3545     if (IS_ALIGNED(width, 8)) {
3546       RGB565ToARGBRow = RGB565ToARGBRow_NEON;
3547     }
3548   }
3549 #endif
3550 #if defined(HAS_RGB565TOARGBROW_MSA)
3551   if (TestCpuFlag(kCpuHasMSA)) {
3552     RGB565ToARGBRow = RGB565ToARGBRow_Any_MSA;
3553     if (IS_ALIGNED(width, 16)) {
3554       RGB565ToARGBRow = RGB565ToARGBRow_MSA;
3555     }
3556   }
3557 #endif
3558 #if defined(HAS_RGB565TOARGBROW_LSX)
3559   if (TestCpuFlag(kCpuHasLSX)) {
3560     RGB565ToARGBRow = RGB565ToARGBRow_Any_LSX;
3561     if (IS_ALIGNED(width, 16)) {
3562       RGB565ToARGBRow = RGB565ToARGBRow_LSX;
3563     }
3564   }
3565 #endif
3566 #if defined(HAS_RGB565TOARGBROW_LASX)
3567   if (TestCpuFlag(kCpuHasLASX)) {
3568     RGB565ToARGBRow = RGB565ToARGBRow_Any_LASX;
3569     if (IS_ALIGNED(width, 32)) {
3570       RGB565ToARGBRow = RGB565ToARGBRow_LASX;
3571     }
3572   }
3573 #endif
3574 
3575   for (y = 0; y < height; ++y) {
3576     RGB565ToARGBRow(src_rgb565, dst_argb, width);
3577     src_rgb565 += src_stride_rgb565;
3578     dst_argb += dst_stride_argb;
3579   }
3580   return 0;
3581 }
3582 
3583 // Convert ARGB1555 to ARGB.
3584 LIBYUV_API
ARGB1555ToARGB(const uint8_t * src_argb1555,int src_stride_argb1555,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3585 int ARGB1555ToARGB(const uint8_t* src_argb1555,
3586                    int src_stride_argb1555,
3587                    uint8_t* dst_argb,
3588                    int dst_stride_argb,
3589                    int width,
3590                    int height) {
3591   int y;
3592   void (*ARGB1555ToARGBRow)(const uint8_t* src_argb1555, uint8_t* dst_argb,
3593                             int width) = ARGB1555ToARGBRow_C;
3594   if (!src_argb1555 || !dst_argb || width <= 0 || height == 0) {
3595     return -1;
3596   }
3597   // Negative height means invert the image.
3598   if (height < 0) {
3599     height = -height;
3600     src_argb1555 = src_argb1555 + (height - 1) * src_stride_argb1555;
3601     src_stride_argb1555 = -src_stride_argb1555;
3602   }
3603   // Coalesce rows.
3604   if (src_stride_argb1555 == width * 2 && dst_stride_argb == width * 4) {
3605     width *= height;
3606     height = 1;
3607     src_stride_argb1555 = dst_stride_argb = 0;
3608   }
3609 #if defined(HAS_ARGB1555TOARGBROW_SSE2)
3610   if (TestCpuFlag(kCpuHasSSE2)) {
3611     ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_SSE2;
3612     if (IS_ALIGNED(width, 8)) {
3613       ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2;
3614     }
3615   }
3616 #endif
3617 #if defined(HAS_ARGB1555TOARGBROW_AVX2)
3618   if (TestCpuFlag(kCpuHasAVX2)) {
3619     ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_AVX2;
3620     if (IS_ALIGNED(width, 16)) {
3621       ARGB1555ToARGBRow = ARGB1555ToARGBRow_AVX2;
3622     }
3623   }
3624 #endif
3625 #if defined(HAS_ARGB1555TOARGBROW_NEON)
3626   if (TestCpuFlag(kCpuHasNEON)) {
3627     ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_NEON;
3628     if (IS_ALIGNED(width, 8)) {
3629       ARGB1555ToARGBRow = ARGB1555ToARGBRow_NEON;
3630     }
3631   }
3632 #endif
3633 #if defined(HAS_ARGB1555TOARGBROW_MSA)
3634   if (TestCpuFlag(kCpuHasMSA)) {
3635     ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_MSA;
3636     if (IS_ALIGNED(width, 16)) {
3637       ARGB1555ToARGBRow = ARGB1555ToARGBRow_MSA;
3638     }
3639   }
3640 #endif
3641 #if defined(HAS_ARGB1555TOARGBROW_LSX)
3642   if (TestCpuFlag(kCpuHasLSX)) {
3643     ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_LSX;
3644     if (IS_ALIGNED(width, 16)) {
3645       ARGB1555ToARGBRow = ARGB1555ToARGBRow_LSX;
3646     }
3647   }
3648 #endif
3649 #if defined(HAS_ARGB1555TOARGBROW_LASX)
3650   if (TestCpuFlag(kCpuHasLASX)) {
3651     ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_LASX;
3652     if (IS_ALIGNED(width, 32)) {
3653       ARGB1555ToARGBRow = ARGB1555ToARGBRow_LASX;
3654     }
3655   }
3656 #endif
3657 
3658   for (y = 0; y < height; ++y) {
3659     ARGB1555ToARGBRow(src_argb1555, dst_argb, width);
3660     src_argb1555 += src_stride_argb1555;
3661     dst_argb += dst_stride_argb;
3662   }
3663   return 0;
3664 }
3665 
3666 // Convert ARGB4444 to ARGB.
3667 LIBYUV_API
ARGB4444ToARGB(const uint8_t * src_argb4444,int src_stride_argb4444,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3668 int ARGB4444ToARGB(const uint8_t* src_argb4444,
3669                    int src_stride_argb4444,
3670                    uint8_t* dst_argb,
3671                    int dst_stride_argb,
3672                    int width,
3673                    int height) {
3674   int y;
3675   void (*ARGB4444ToARGBRow)(const uint8_t* src_argb4444, uint8_t* dst_argb,
3676                             int width) = ARGB4444ToARGBRow_C;
3677   if (!src_argb4444 || !dst_argb || width <= 0 || height == 0) {
3678     return -1;
3679   }
3680   // Negative height means invert the image.
3681   if (height < 0) {
3682     height = -height;
3683     src_argb4444 = src_argb4444 + (height - 1) * src_stride_argb4444;
3684     src_stride_argb4444 = -src_stride_argb4444;
3685   }
3686   // Coalesce rows.
3687   if (src_stride_argb4444 == width * 2 && dst_stride_argb == width * 4) {
3688     width *= height;
3689     height = 1;
3690     src_stride_argb4444 = dst_stride_argb = 0;
3691   }
3692 #if defined(HAS_ARGB4444TOARGBROW_SSE2)
3693   if (TestCpuFlag(kCpuHasSSE2)) {
3694     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_SSE2;
3695     if (IS_ALIGNED(width, 8)) {
3696       ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2;
3697     }
3698   }
3699 #endif
3700 #if defined(HAS_ARGB4444TOARGBROW_AVX2)
3701   if (TestCpuFlag(kCpuHasAVX2)) {
3702     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_AVX2;
3703     if (IS_ALIGNED(width, 16)) {
3704       ARGB4444ToARGBRow = ARGB4444ToARGBRow_AVX2;
3705     }
3706   }
3707 #endif
3708 #if defined(HAS_ARGB4444TOARGBROW_NEON)
3709   if (TestCpuFlag(kCpuHasNEON)) {
3710     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_NEON;
3711     if (IS_ALIGNED(width, 8)) {
3712       ARGB4444ToARGBRow = ARGB4444ToARGBRow_NEON;
3713     }
3714   }
3715 #endif
3716 #if defined(HAS_ARGB4444TOARGBROW_MSA)
3717   if (TestCpuFlag(kCpuHasMSA)) {
3718     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_MSA;
3719     if (IS_ALIGNED(width, 16)) {
3720       ARGB4444ToARGBRow = ARGB4444ToARGBRow_MSA;
3721     }
3722   }
3723 #endif
3724 #if defined(HAS_ARGB4444TOARGBROW_LSX)
3725   if (TestCpuFlag(kCpuHasLSX)) {
3726     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_LSX;
3727     if (IS_ALIGNED(width, 16)) {
3728       ARGB4444ToARGBRow = ARGB4444ToARGBRow_LSX;
3729     }
3730   }
3731 #endif
3732 #if defined(HAS_ARGB4444TOARGBROW_LASX)
3733   if (TestCpuFlag(kCpuHasLASX)) {
3734     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_LASX;
3735     if (IS_ALIGNED(width, 32)) {
3736       ARGB4444ToARGBRow = ARGB4444ToARGBRow_LASX;
3737     }
3738   }
3739 #endif
3740 
3741   for (y = 0; y < height; ++y) {
3742     ARGB4444ToARGBRow(src_argb4444, dst_argb, width);
3743     src_argb4444 += src_stride_argb4444;
3744     dst_argb += dst_stride_argb;
3745   }
3746   return 0;
3747 }
3748 
3749 // Convert AR30 to ARGB.
3750 LIBYUV_API
AR30ToARGB(const uint8_t * src_ar30,int src_stride_ar30,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3751 int AR30ToARGB(const uint8_t* src_ar30,
3752                int src_stride_ar30,
3753                uint8_t* dst_argb,
3754                int dst_stride_argb,
3755                int width,
3756                int height) {
3757   int y;
3758   if (!src_ar30 || !dst_argb || width <= 0 || height == 0) {
3759     return -1;
3760   }
3761   // Negative height means invert the image.
3762   if (height < 0) {
3763     height = -height;
3764     src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
3765     src_stride_ar30 = -src_stride_ar30;
3766   }
3767   // Coalesce rows.
3768   if (src_stride_ar30 == width * 4 && dst_stride_argb == width * 4) {
3769     width *= height;
3770     height = 1;
3771     src_stride_ar30 = dst_stride_argb = 0;
3772   }
3773   for (y = 0; y < height; ++y) {
3774     AR30ToARGBRow_C(src_ar30, dst_argb, width);
3775     src_ar30 += src_stride_ar30;
3776     dst_argb += dst_stride_argb;
3777   }
3778   return 0;
3779 }
3780 
3781 // Convert AR30 to ABGR.
3782 LIBYUV_API
AR30ToABGR(const uint8_t * src_ar30,int src_stride_ar30,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)3783 int AR30ToABGR(const uint8_t* src_ar30,
3784                int src_stride_ar30,
3785                uint8_t* dst_abgr,
3786                int dst_stride_abgr,
3787                int width,
3788                int height) {
3789   int y;
3790   if (!src_ar30 || !dst_abgr || width <= 0 || height == 0) {
3791     return -1;
3792   }
3793   // Negative height means invert the image.
3794   if (height < 0) {
3795     height = -height;
3796     src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
3797     src_stride_ar30 = -src_stride_ar30;
3798   }
3799   // Coalesce rows.
3800   if (src_stride_ar30 == width * 4 && dst_stride_abgr == width * 4) {
3801     width *= height;
3802     height = 1;
3803     src_stride_ar30 = dst_stride_abgr = 0;
3804   }
3805   for (y = 0; y < height; ++y) {
3806     AR30ToABGRRow_C(src_ar30, dst_abgr, width);
3807     src_ar30 += src_stride_ar30;
3808     dst_abgr += dst_stride_abgr;
3809   }
3810   return 0;
3811 }
3812 
3813 // Convert AR30 to AB30.
3814 LIBYUV_API
AR30ToAB30(const uint8_t * src_ar30,int src_stride_ar30,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)3815 int AR30ToAB30(const uint8_t* src_ar30,
3816                int src_stride_ar30,
3817                uint8_t* dst_ab30,
3818                int dst_stride_ab30,
3819                int width,
3820                int height) {
3821   int y;
3822   if (!src_ar30 || !dst_ab30 || width <= 0 || height == 0) {
3823     return -1;
3824   }
3825   // Negative height means invert the image.
3826   if (height < 0) {
3827     height = -height;
3828     src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
3829     src_stride_ar30 = -src_stride_ar30;
3830   }
3831   // Coalesce rows.
3832   if (src_stride_ar30 == width * 4 && dst_stride_ab30 == width * 4) {
3833     width *= height;
3834     height = 1;
3835     src_stride_ar30 = dst_stride_ab30 = 0;
3836   }
3837   for (y = 0; y < height; ++y) {
3838     AR30ToAB30Row_C(src_ar30, dst_ab30, width);
3839     src_ar30 += src_stride_ar30;
3840     dst_ab30 += dst_stride_ab30;
3841   }
3842   return 0;
3843 }
3844 
3845 // Convert AR64 to ARGB.
3846 LIBYUV_API
AR64ToARGB(const uint16_t * src_ar64,int src_stride_ar64,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3847 int AR64ToARGB(const uint16_t* src_ar64,
3848                int src_stride_ar64,
3849                uint8_t* dst_argb,
3850                int dst_stride_argb,
3851                int width,
3852                int height) {
3853   int y;
3854   void (*AR64ToARGBRow)(const uint16_t* src_ar64, uint8_t* dst_argb,
3855                         int width) = AR64ToARGBRow_C;
3856   if (!src_ar64 || !dst_argb || width <= 0 || height == 0) {
3857     return -1;
3858   }
3859   // Negative height means invert the image.
3860   if (height < 0) {
3861     height = -height;
3862     src_ar64 = src_ar64 + (height - 1) * src_stride_ar64;
3863     src_stride_ar64 = -src_stride_ar64;
3864   }
3865   // Coalesce rows.
3866   if (src_stride_ar64 == width * 4 && dst_stride_argb == width * 4) {
3867     width *= height;
3868     height = 1;
3869     src_stride_ar64 = dst_stride_argb = 0;
3870   }
3871 #if defined(HAS_AR64TOARGBROW_SSSE3)
3872   if (TestCpuFlag(kCpuHasSSSE3)) {
3873     AR64ToARGBRow = AR64ToARGBRow_Any_SSSE3;
3874     if (IS_ALIGNED(width, 4)) {
3875       AR64ToARGBRow = AR64ToARGBRow_SSSE3;
3876     }
3877   }
3878 #endif
3879 #if defined(HAS_AR64TOARGBROW_AVX2)
3880   if (TestCpuFlag(kCpuHasAVX2)) {
3881     AR64ToARGBRow = AR64ToARGBRow_Any_AVX2;
3882     if (IS_ALIGNED(width, 8)) {
3883       AR64ToARGBRow = AR64ToARGBRow_AVX2;
3884     }
3885   }
3886 #endif
3887 #if defined(HAS_AR64TOARGBROW_NEON)
3888   if (TestCpuFlag(kCpuHasNEON)) {
3889     AR64ToARGBRow = AR64ToARGBRow_Any_NEON;
3890     if (IS_ALIGNED(width, 8)) {
3891       AR64ToARGBRow = AR64ToARGBRow_NEON;
3892     }
3893   }
3894 #endif
3895 #if defined(HAS_AR64TOARGBROW_RVV)
3896   if (TestCpuFlag(kCpuHasRVV)) {
3897     AR64ToARGBRow = AR64ToARGBRow_RVV;
3898   }
3899 #endif
3900 
3901   for (y = 0; y < height; ++y) {
3902     AR64ToARGBRow(src_ar64, dst_argb, width);
3903     src_ar64 += src_stride_ar64;
3904     dst_argb += dst_stride_argb;
3905   }
3906   return 0;
3907 }
3908 
3909 // Convert AB64 to ARGB.
3910 LIBYUV_API
AB64ToARGB(const uint16_t * src_ab64,int src_stride_ab64,uint8_t * dst_argb,int dst_stride_argb,int width,int height)3911 int AB64ToARGB(const uint16_t* src_ab64,
3912                int src_stride_ab64,
3913                uint8_t* dst_argb,
3914                int dst_stride_argb,
3915                int width,
3916                int height) {
3917   int y;
3918   void (*AB64ToARGBRow)(const uint16_t* src_ar64, uint8_t* dst_argb,
3919                         int width) = AB64ToARGBRow_C;
3920   if (!src_ab64 || !dst_argb || width <= 0 || height == 0) {
3921     return -1;
3922   }
3923   // Negative height means invert the image.
3924   if (height < 0) {
3925     height = -height;
3926     src_ab64 = src_ab64 + (height - 1) * src_stride_ab64;
3927     src_stride_ab64 = -src_stride_ab64;
3928   }
3929   // Coalesce rows.
3930   if (src_stride_ab64 == width * 4 && dst_stride_argb == width * 4) {
3931     width *= height;
3932     height = 1;
3933     src_stride_ab64 = dst_stride_argb = 0;
3934   }
3935 #if defined(HAS_AB64TOARGBROW_SSSE3)
3936   if (TestCpuFlag(kCpuHasSSSE3)) {
3937     AB64ToARGBRow = AB64ToARGBRow_Any_SSSE3;
3938     if (IS_ALIGNED(width, 4)) {
3939       AB64ToARGBRow = AB64ToARGBRow_SSSE3;
3940     }
3941   }
3942 #endif
3943 #if defined(HAS_AB64TOARGBROW_AVX2)
3944   if (TestCpuFlag(kCpuHasAVX2)) {
3945     AB64ToARGBRow = AB64ToARGBRow_Any_AVX2;
3946     if (IS_ALIGNED(width, 8)) {
3947       AB64ToARGBRow = AB64ToARGBRow_AVX2;
3948     }
3949   }
3950 #endif
3951 #if defined(HAS_AB64TOARGBROW_NEON)
3952   if (TestCpuFlag(kCpuHasNEON)) {
3953     AB64ToARGBRow = AB64ToARGBRow_Any_NEON;
3954     if (IS_ALIGNED(width, 8)) {
3955       AB64ToARGBRow = AB64ToARGBRow_NEON;
3956     }
3957   }
3958 #endif
3959 #if defined(HAS_AB64TOARGBROW_RVV)
3960   if (TestCpuFlag(kCpuHasRVV)) {
3961     AB64ToARGBRow = AB64ToARGBRow_RVV;
3962   }
3963 #endif
3964 
3965   for (y = 0; y < height; ++y) {
3966     AB64ToARGBRow(src_ab64, dst_argb, width);
3967     src_ab64 += src_stride_ab64;
3968     dst_argb += dst_stride_argb;
3969   }
3970   return 0;
3971 }
3972 
3973 // Convert NV12 to ARGB with matrix.
3974 LIBYUV_API
NV12ToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)3975 int NV12ToARGBMatrix(const uint8_t* src_y,
3976                      int src_stride_y,
3977                      const uint8_t* src_uv,
3978                      int src_stride_uv,
3979                      uint8_t* dst_argb,
3980                      int dst_stride_argb,
3981                      const struct YuvConstants* yuvconstants,
3982                      int width,
3983                      int height) {
3984   int y;
3985   void (*NV12ToARGBRow)(
3986       const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
3987       const struct YuvConstants* yuvconstants, int width) = NV12ToARGBRow_C;
3988   assert(yuvconstants);
3989   if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
3990     return -1;
3991   }
3992   // Negative height means invert the image.
3993   if (height < 0) {
3994     height = -height;
3995     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
3996     dst_stride_argb = -dst_stride_argb;
3997   }
3998 #if defined(HAS_NV12TOARGBROW_SSSE3)
3999   if (TestCpuFlag(kCpuHasSSSE3)) {
4000     NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
4001     if (IS_ALIGNED(width, 8)) {
4002       NV12ToARGBRow = NV12ToARGBRow_SSSE3;
4003     }
4004   }
4005 #endif
4006 #if defined(HAS_NV12TOARGBROW_AVX2)
4007   if (TestCpuFlag(kCpuHasAVX2)) {
4008     NV12ToARGBRow = NV12ToARGBRow_Any_AVX2;
4009     if (IS_ALIGNED(width, 16)) {
4010       NV12ToARGBRow = NV12ToARGBRow_AVX2;
4011     }
4012   }
4013 #endif
4014 #if defined(HAS_NV12TOARGBROW_NEON)
4015   if (TestCpuFlag(kCpuHasNEON)) {
4016     NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
4017     if (IS_ALIGNED(width, 8)) {
4018       NV12ToARGBRow = NV12ToARGBRow_NEON;
4019     }
4020   }
4021 #endif
4022 #if defined(HAS_NV12TOARGBROW_MSA)
4023   if (TestCpuFlag(kCpuHasMSA)) {
4024     NV12ToARGBRow = NV12ToARGBRow_Any_MSA;
4025     if (IS_ALIGNED(width, 8)) {
4026       NV12ToARGBRow = NV12ToARGBRow_MSA;
4027     }
4028   }
4029 #endif
4030 #if defined(HAS_NV12TOARGBROW_LSX)
4031   if (TestCpuFlag(kCpuHasLSX)) {
4032     NV12ToARGBRow = NV12ToARGBRow_Any_LSX;
4033     if (IS_ALIGNED(width, 8)) {
4034       NV12ToARGBRow = NV12ToARGBRow_LSX;
4035     }
4036   }
4037 #endif
4038 #if defined(HAS_NV12TOARGBROW_LASX)
4039   if (TestCpuFlag(kCpuHasLASX)) {
4040     NV12ToARGBRow = NV12ToARGBRow_Any_LASX;
4041     if (IS_ALIGNED(width, 16)) {
4042       NV12ToARGBRow = NV12ToARGBRow_LASX;
4043     }
4044   }
4045 #endif
4046 #if defined(HAS_NV12TOARGBROW_RVV)
4047   if (TestCpuFlag(kCpuHasRVV)) {
4048     NV12ToARGBRow = NV12ToARGBRow_RVV;
4049   }
4050 #endif
4051 
4052   for (y = 0; y < height; ++y) {
4053     NV12ToARGBRow(src_y, src_uv, dst_argb, yuvconstants, width);
4054     dst_argb += dst_stride_argb;
4055     src_y += src_stride_y;
4056     if (y & 1) {
4057       src_uv += src_stride_uv;
4058     }
4059   }
4060   return 0;
4061 }
4062 
4063 // Convert NV21 to ARGB with matrix.
4064 LIBYUV_API
NV21ToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_vu,int src_stride_vu,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)4065 int NV21ToARGBMatrix(const uint8_t* src_y,
4066                      int src_stride_y,
4067                      const uint8_t* src_vu,
4068                      int src_stride_vu,
4069                      uint8_t* dst_argb,
4070                      int dst_stride_argb,
4071                      const struct YuvConstants* yuvconstants,
4072                      int width,
4073                      int height) {
4074   int y;
4075   void (*NV21ToARGBRow)(
4076       const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
4077       const struct YuvConstants* yuvconstants, int width) = NV21ToARGBRow_C;
4078   assert(yuvconstants);
4079   if (!src_y || !src_vu || !dst_argb || width <= 0 || height == 0) {
4080     return -1;
4081   }
4082   // Negative height means invert the image.
4083   if (height < 0) {
4084     height = -height;
4085     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
4086     dst_stride_argb = -dst_stride_argb;
4087   }
4088 #if defined(HAS_NV21TOARGBROW_SSSE3)
4089   if (TestCpuFlag(kCpuHasSSSE3)) {
4090     NV21ToARGBRow = NV21ToARGBRow_Any_SSSE3;
4091     if (IS_ALIGNED(width, 8)) {
4092       NV21ToARGBRow = NV21ToARGBRow_SSSE3;
4093     }
4094   }
4095 #endif
4096 #if defined(HAS_NV21TOARGBROW_AVX2)
4097   if (TestCpuFlag(kCpuHasAVX2)) {
4098     NV21ToARGBRow = NV21ToARGBRow_Any_AVX2;
4099     if (IS_ALIGNED(width, 16)) {
4100       NV21ToARGBRow = NV21ToARGBRow_AVX2;
4101     }
4102   }
4103 #endif
4104 #if defined(HAS_NV21TOARGBROW_NEON)
4105   if (TestCpuFlag(kCpuHasNEON)) {
4106     NV21ToARGBRow = NV21ToARGBRow_Any_NEON;
4107     if (IS_ALIGNED(width, 8)) {
4108       NV21ToARGBRow = NV21ToARGBRow_NEON;
4109     }
4110   }
4111 #endif
4112 #if defined(HAS_NV21TOARGBROW_MSA)
4113   if (TestCpuFlag(kCpuHasMSA)) {
4114     NV21ToARGBRow = NV21ToARGBRow_Any_MSA;
4115     if (IS_ALIGNED(width, 8)) {
4116       NV21ToARGBRow = NV21ToARGBRow_MSA;
4117     }
4118   }
4119 #endif
4120 #if defined(HAS_NV21TOARGBROW_LSX)
4121   if (TestCpuFlag(kCpuHasLSX)) {
4122     NV21ToARGBRow = NV21ToARGBRow_Any_LSX;
4123     if (IS_ALIGNED(width, 8)) {
4124       NV21ToARGBRow = NV21ToARGBRow_LSX;
4125     }
4126   }
4127 #endif
4128 #if defined(HAS_NV21TOARGBROW_LASX)
4129   if (TestCpuFlag(kCpuHasLASX)) {
4130     NV21ToARGBRow = NV21ToARGBRow_Any_LASX;
4131     if (IS_ALIGNED(width, 16)) {
4132       NV21ToARGBRow = NV21ToARGBRow_LASX;
4133     }
4134   }
4135 #endif
4136 #if defined(HAS_NV21TOARGBROW_RVV)
4137   if (TestCpuFlag(kCpuHasRVV)) {
4138     NV21ToARGBRow = NV21ToARGBRow_RVV;
4139   }
4140 #endif
4141 
4142   for (y = 0; y < height; ++y) {
4143     NV21ToARGBRow(src_y, src_vu, dst_argb, yuvconstants, width);
4144     dst_argb += dst_stride_argb;
4145     src_y += src_stride_y;
4146     if (y & 1) {
4147       src_vu += src_stride_vu;
4148     }
4149   }
4150   return 0;
4151 }
4152 
4153 // Convert NV12 to ARGB.
4154 LIBYUV_API
NV12ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_argb,int dst_stride_argb,int width,int height)4155 int NV12ToARGB(const uint8_t* src_y,
4156                int src_stride_y,
4157                const uint8_t* src_uv,
4158                int src_stride_uv,
4159                uint8_t* dst_argb,
4160                int dst_stride_argb,
4161                int width,
4162                int height) {
4163   return NV12ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_argb,
4164                           dst_stride_argb, &kYuvI601Constants, width, height);
4165 }
4166 
4167 // Convert NV21 to ARGB.
4168 LIBYUV_API
NV21ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_vu,int src_stride_vu,uint8_t * dst_argb,int dst_stride_argb,int width,int height)4169 int NV21ToARGB(const uint8_t* src_y,
4170                int src_stride_y,
4171                const uint8_t* src_vu,
4172                int src_stride_vu,
4173                uint8_t* dst_argb,
4174                int dst_stride_argb,
4175                int width,
4176                int height) {
4177   return NV21ToARGBMatrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_argb,
4178                           dst_stride_argb, &kYuvI601Constants, width, height);
4179 }
4180 
4181 // Convert NV12 to ABGR.
4182 // To output ABGR instead of ARGB swap the UV and use a mirrored yuv matrix.
4183 // To swap the UV use NV12 instead of NV21.LIBYUV_API
4184 LIBYUV_API
NV12ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)4185 int NV12ToABGR(const uint8_t* src_y,
4186                int src_stride_y,
4187                const uint8_t* src_uv,
4188                int src_stride_uv,
4189                uint8_t* dst_abgr,
4190                int dst_stride_abgr,
4191                int width,
4192                int height) {
4193   return NV21ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_abgr,
4194                           dst_stride_abgr, &kYvuI601Constants, width, height);
4195 }
4196 
4197 // Convert NV21 to ABGR.
4198 LIBYUV_API
NV21ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_vu,int src_stride_vu,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)4199 int NV21ToABGR(const uint8_t* src_y,
4200                int src_stride_y,
4201                const uint8_t* src_vu,
4202                int src_stride_vu,
4203                uint8_t* dst_abgr,
4204                int dst_stride_abgr,
4205                int width,
4206                int height) {
4207   return NV12ToARGBMatrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_abgr,
4208                           dst_stride_abgr, &kYvuI601Constants, width, height);
4209 }
4210 
4211 // TODO(fbarchard): Consider SSSE3 2 step conversion.
4212 // Convert NV12 to RGB24 with matrix.
4213 LIBYUV_API
NV12ToRGB24Matrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_rgb24,int dst_stride_rgb24,const struct YuvConstants * yuvconstants,int width,int height)4214 int NV12ToRGB24Matrix(const uint8_t* src_y,
4215                       int src_stride_y,
4216                       const uint8_t* src_uv,
4217                       int src_stride_uv,
4218                       uint8_t* dst_rgb24,
4219                       int dst_stride_rgb24,
4220                       const struct YuvConstants* yuvconstants,
4221                       int width,
4222                       int height) {
4223   int y;
4224   void (*NV12ToRGB24Row)(
4225       const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
4226       const struct YuvConstants* yuvconstants, int width) = NV12ToRGB24Row_C;
4227   assert(yuvconstants);
4228   if (!src_y || !src_uv || !dst_rgb24 || width <= 0 || height == 0) {
4229     return -1;
4230   }
4231   // Negative height means invert the image.
4232   if (height < 0) {
4233     height = -height;
4234     dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
4235     dst_stride_rgb24 = -dst_stride_rgb24;
4236   }
4237 #if defined(HAS_NV12TORGB24ROW_NEON)
4238   if (TestCpuFlag(kCpuHasNEON)) {
4239     NV12ToRGB24Row = NV12ToRGB24Row_Any_NEON;
4240     if (IS_ALIGNED(width, 8)) {
4241       NV12ToRGB24Row = NV12ToRGB24Row_NEON;
4242     }
4243   }
4244 #endif
4245 #if defined(HAS_NV12TORGB24ROW_SSSE3)
4246   if (TestCpuFlag(kCpuHasSSSE3)) {
4247     NV12ToRGB24Row = NV12ToRGB24Row_Any_SSSE3;
4248     if (IS_ALIGNED(width, 16)) {
4249       NV12ToRGB24Row = NV12ToRGB24Row_SSSE3;
4250     }
4251   }
4252 #endif
4253 #if defined(HAS_NV12TORGB24ROW_AVX2)
4254   if (TestCpuFlag(kCpuHasAVX2)) {
4255     NV12ToRGB24Row = NV12ToRGB24Row_Any_AVX2;
4256     if (IS_ALIGNED(width, 32)) {
4257       NV12ToRGB24Row = NV12ToRGB24Row_AVX2;
4258     }
4259   }
4260 #endif
4261 #if defined(HAS_NV12TORGB24ROW_RVV)
4262   if (TestCpuFlag(kCpuHasRVV)) {
4263     NV12ToRGB24Row = NV12ToRGB24Row_RVV;
4264   }
4265 #endif
4266 
4267   for (y = 0; y < height; ++y) {
4268     NV12ToRGB24Row(src_y, src_uv, dst_rgb24, yuvconstants, width);
4269     dst_rgb24 += dst_stride_rgb24;
4270     src_y += src_stride_y;
4271     if (y & 1) {
4272       src_uv += src_stride_uv;
4273     }
4274   }
4275   return 0;
4276 }
4277 
4278 // Convert NV21 to RGB24 with matrix.
4279 LIBYUV_API
NV21ToRGB24Matrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_vu,int src_stride_vu,uint8_t * dst_rgb24,int dst_stride_rgb24,const struct YuvConstants * yuvconstants,int width,int height)4280 int NV21ToRGB24Matrix(const uint8_t* src_y,
4281                       int src_stride_y,
4282                       const uint8_t* src_vu,
4283                       int src_stride_vu,
4284                       uint8_t* dst_rgb24,
4285                       int dst_stride_rgb24,
4286                       const struct YuvConstants* yuvconstants,
4287                       int width,
4288                       int height) {
4289   int y;
4290   void (*NV21ToRGB24Row)(
4291       const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
4292       const struct YuvConstants* yuvconstants, int width) = NV21ToRGB24Row_C;
4293   assert(yuvconstants);
4294   if (!src_y || !src_vu || !dst_rgb24 || width <= 0 || height == 0) {
4295     return -1;
4296   }
4297   // Negative height means invert the image.
4298   if (height < 0) {
4299     height = -height;
4300     dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
4301     dst_stride_rgb24 = -dst_stride_rgb24;
4302   }
4303 #if defined(HAS_NV21TORGB24ROW_NEON)
4304   if (TestCpuFlag(kCpuHasNEON)) {
4305     NV21ToRGB24Row = NV21ToRGB24Row_Any_NEON;
4306     if (IS_ALIGNED(width, 8)) {
4307       NV21ToRGB24Row = NV21ToRGB24Row_NEON;
4308     }
4309   }
4310 #endif
4311 #if defined(HAS_NV21TORGB24ROW_SSSE3)
4312   if (TestCpuFlag(kCpuHasSSSE3)) {
4313     NV21ToRGB24Row = NV21ToRGB24Row_Any_SSSE3;
4314     if (IS_ALIGNED(width, 16)) {
4315       NV21ToRGB24Row = NV21ToRGB24Row_SSSE3;
4316     }
4317   }
4318 #endif
4319 #if defined(HAS_NV21TORGB24ROW_AVX2)
4320   if (TestCpuFlag(kCpuHasAVX2)) {
4321     NV21ToRGB24Row = NV21ToRGB24Row_Any_AVX2;
4322     if (IS_ALIGNED(width, 32)) {
4323       NV21ToRGB24Row = NV21ToRGB24Row_AVX2;
4324     }
4325   }
4326 #endif
4327 #if defined(HAS_NV21TORGB24ROW_RVV)
4328   if (TestCpuFlag(kCpuHasRVV)) {
4329     NV21ToRGB24Row = NV21ToRGB24Row_RVV;
4330   }
4331 #endif
4332 
4333   for (y = 0; y < height; ++y) {
4334     NV21ToRGB24Row(src_y, src_vu, dst_rgb24, yuvconstants, width);
4335     dst_rgb24 += dst_stride_rgb24;
4336     src_y += src_stride_y;
4337     if (y & 1) {
4338       src_vu += src_stride_vu;
4339     }
4340   }
4341   return 0;
4342 }
4343 
4344 // Convert NV12 to RGB24.
4345 LIBYUV_API
NV12ToRGB24(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_rgb24,int dst_stride_rgb24,int width,int height)4346 int NV12ToRGB24(const uint8_t* src_y,
4347                 int src_stride_y,
4348                 const uint8_t* src_uv,
4349                 int src_stride_uv,
4350                 uint8_t* dst_rgb24,
4351                 int dst_stride_rgb24,
4352                 int width,
4353                 int height) {
4354   return NV12ToRGB24Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
4355                            dst_rgb24, dst_stride_rgb24, &kYuvI601Constants,
4356                            width, height);
4357 }
4358 
4359 // Convert NV21 to RGB24.
4360 LIBYUV_API
NV21ToRGB24(const uint8_t * src_y,int src_stride_y,const uint8_t * src_vu,int src_stride_vu,uint8_t * dst_rgb24,int dst_stride_rgb24,int width,int height)4361 int NV21ToRGB24(const uint8_t* src_y,
4362                 int src_stride_y,
4363                 const uint8_t* src_vu,
4364                 int src_stride_vu,
4365                 uint8_t* dst_rgb24,
4366                 int dst_stride_rgb24,
4367                 int width,
4368                 int height) {
4369   return NV21ToRGB24Matrix(src_y, src_stride_y, src_vu, src_stride_vu,
4370                            dst_rgb24, dst_stride_rgb24, &kYuvI601Constants,
4371                            width, height);
4372 }
4373 
4374 // Convert NV12 to RAW.
4375 LIBYUV_API
NV12ToRAW(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_raw,int dst_stride_raw,int width,int height)4376 int NV12ToRAW(const uint8_t* src_y,
4377               int src_stride_y,
4378               const uint8_t* src_uv,
4379               int src_stride_uv,
4380               uint8_t* dst_raw,
4381               int dst_stride_raw,
4382               int width,
4383               int height) {
4384   return NV21ToRGB24Matrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_raw,
4385                            dst_stride_raw, &kYvuI601Constants, width, height);
4386 }
4387 
4388 // Convert NV21 to RAW.
4389 LIBYUV_API
NV21ToRAW(const uint8_t * src_y,int src_stride_y,const uint8_t * src_vu,int src_stride_vu,uint8_t * dst_raw,int dst_stride_raw,int width,int height)4390 int NV21ToRAW(const uint8_t* src_y,
4391               int src_stride_y,
4392               const uint8_t* src_vu,
4393               int src_stride_vu,
4394               uint8_t* dst_raw,
4395               int dst_stride_raw,
4396               int width,
4397               int height) {
4398   return NV12ToRGB24Matrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_raw,
4399                            dst_stride_raw, &kYvuI601Constants, width, height);
4400 }
4401 
4402 // Convert NV21 to YUV24
NV21ToYUV24(const uint8_t * src_y,int src_stride_y,const uint8_t * src_vu,int src_stride_vu,uint8_t * dst_yuv24,int dst_stride_yuv24,int width,int height)4403 int NV21ToYUV24(const uint8_t* src_y,
4404                 int src_stride_y,
4405                 const uint8_t* src_vu,
4406                 int src_stride_vu,
4407                 uint8_t* dst_yuv24,
4408                 int dst_stride_yuv24,
4409                 int width,
4410                 int height) {
4411   int y;
4412   void (*NV21ToYUV24Row)(const uint8_t* src_y, const uint8_t* src_vu,
4413                          uint8_t* dst_yuv24, int width) = NV21ToYUV24Row_C;
4414   if (!src_y || !src_vu || !dst_yuv24 || width <= 0 || height == 0) {
4415     return -1;
4416   }
4417   // Negative height means invert the image.
4418   if (height < 0) {
4419     height = -height;
4420     dst_yuv24 = dst_yuv24 + (height - 1) * dst_stride_yuv24;
4421     dst_stride_yuv24 = -dst_stride_yuv24;
4422   }
4423 #if defined(HAS_NV21TOYUV24ROW_NEON)
4424   if (TestCpuFlag(kCpuHasNEON)) {
4425     NV21ToYUV24Row = NV21ToYUV24Row_Any_NEON;
4426     if (IS_ALIGNED(width, 16)) {
4427       NV21ToYUV24Row = NV21ToYUV24Row_NEON;
4428     }
4429   }
4430 #endif
4431 #if defined(HAS_NV21TOYUV24ROW_SSSE3)
4432   if (TestCpuFlag(kCpuHasSSSE3)) {
4433     NV21ToYUV24Row = NV21ToYUV24Row_Any_SSSE3;
4434     if (IS_ALIGNED(width, 16)) {
4435       NV21ToYUV24Row = NV21ToYUV24Row_SSSE3;
4436     }
4437   }
4438 #endif
4439 #if defined(HAS_NV21TOYUV24ROW_AVX2)
4440   if (TestCpuFlag(kCpuHasAVX2)) {
4441     NV21ToYUV24Row = NV21ToYUV24Row_Any_AVX2;
4442     if (IS_ALIGNED(width, 32)) {
4443       NV21ToYUV24Row = NV21ToYUV24Row_AVX2;
4444     }
4445   }
4446 #endif
4447   for (y = 0; y < height; ++y) {
4448     NV21ToYUV24Row(src_y, src_vu, dst_yuv24, width);
4449     dst_yuv24 += dst_stride_yuv24;
4450     src_y += src_stride_y;
4451     if (y & 1) {
4452       src_vu += src_stride_vu;
4453     }
4454   }
4455   return 0;
4456 }
4457 
4458 // Convert YUY2 to ARGB.
4459 LIBYUV_API
YUY2ToARGB(const uint8_t * src_yuy2,int src_stride_yuy2,uint8_t * dst_argb,int dst_stride_argb,int width,int height)4460 int YUY2ToARGB(const uint8_t* src_yuy2,
4461                int src_stride_yuy2,
4462                uint8_t* dst_argb,
4463                int dst_stride_argb,
4464                int width,
4465                int height) {
4466   int y;
4467   void (*YUY2ToARGBRow)(const uint8_t* src_yuy2, uint8_t* dst_argb,
4468                         const struct YuvConstants* yuvconstants, int width) =
4469       YUY2ToARGBRow_C;
4470   if (!src_yuy2 || !dst_argb || width <= 0 || height == 0) {
4471     return -1;
4472   }
4473   // Negative height means invert the image.
4474   if (height < 0) {
4475     height = -height;
4476     src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
4477     src_stride_yuy2 = -src_stride_yuy2;
4478   }
4479   // Coalesce rows.
4480   if (src_stride_yuy2 == width * 2 && dst_stride_argb == width * 4) {
4481     width *= height;
4482     height = 1;
4483     src_stride_yuy2 = dst_stride_argb = 0;
4484   }
4485 #if defined(HAS_YUY2TOARGBROW_SSSE3)
4486   if (TestCpuFlag(kCpuHasSSSE3)) {
4487     YUY2ToARGBRow = YUY2ToARGBRow_Any_SSSE3;
4488     if (IS_ALIGNED(width, 16)) {
4489       YUY2ToARGBRow = YUY2ToARGBRow_SSSE3;
4490     }
4491   }
4492 #endif
4493 #if defined(HAS_YUY2TOARGBROW_AVX2)
4494   if (TestCpuFlag(kCpuHasAVX2)) {
4495     YUY2ToARGBRow = YUY2ToARGBRow_Any_AVX2;
4496     if (IS_ALIGNED(width, 32)) {
4497       YUY2ToARGBRow = YUY2ToARGBRow_AVX2;
4498     }
4499   }
4500 #endif
4501 #if defined(HAS_YUY2TOARGBROW_NEON)
4502   if (TestCpuFlag(kCpuHasNEON)) {
4503     YUY2ToARGBRow = YUY2ToARGBRow_Any_NEON;
4504     if (IS_ALIGNED(width, 8)) {
4505       YUY2ToARGBRow = YUY2ToARGBRow_NEON;
4506     }
4507   }
4508 #endif
4509 #if defined(HAS_YUY2TOARGBROW_MSA)
4510   if (TestCpuFlag(kCpuHasMSA)) {
4511     YUY2ToARGBRow = YUY2ToARGBRow_Any_MSA;
4512     if (IS_ALIGNED(width, 8)) {
4513       YUY2ToARGBRow = YUY2ToARGBRow_MSA;
4514     }
4515   }
4516 #endif
4517 #if defined(HAS_YUY2TOARGBROW_LSX)
4518   if (TestCpuFlag(kCpuHasLSX)) {
4519     YUY2ToARGBRow = YUY2ToARGBRow_Any_LSX;
4520     if (IS_ALIGNED(width, 8)) {
4521       YUY2ToARGBRow = YUY2ToARGBRow_LSX;
4522     }
4523   }
4524 #endif
4525   for (y = 0; y < height; ++y) {
4526     YUY2ToARGBRow(src_yuy2, dst_argb, &kYuvI601Constants, width);
4527     src_yuy2 += src_stride_yuy2;
4528     dst_argb += dst_stride_argb;
4529   }
4530   return 0;
4531 }
4532 
4533 // Convert UYVY to ARGB.
4534 LIBYUV_API
UYVYToARGB(const uint8_t * src_uyvy,int src_stride_uyvy,uint8_t * dst_argb,int dst_stride_argb,int width,int height)4535 int UYVYToARGB(const uint8_t* src_uyvy,
4536                int src_stride_uyvy,
4537                uint8_t* dst_argb,
4538                int dst_stride_argb,
4539                int width,
4540                int height) {
4541   int y;
4542   void (*UYVYToARGBRow)(const uint8_t* src_uyvy, uint8_t* dst_argb,
4543                         const struct YuvConstants* yuvconstants, int width) =
4544       UYVYToARGBRow_C;
4545   if (!src_uyvy || !dst_argb || width <= 0 || height == 0) {
4546     return -1;
4547   }
4548   // Negative height means invert the image.
4549   if (height < 0) {
4550     height = -height;
4551     src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
4552     src_stride_uyvy = -src_stride_uyvy;
4553   }
4554   // Coalesce rows.
4555   if (src_stride_uyvy == width * 2 && dst_stride_argb == width * 4) {
4556     width *= height;
4557     height = 1;
4558     src_stride_uyvy = dst_stride_argb = 0;
4559   }
4560 #if defined(HAS_UYVYTOARGBROW_SSSE3)
4561   if (TestCpuFlag(kCpuHasSSSE3)) {
4562     UYVYToARGBRow = UYVYToARGBRow_Any_SSSE3;
4563     if (IS_ALIGNED(width, 16)) {
4564       UYVYToARGBRow = UYVYToARGBRow_SSSE3;
4565     }
4566   }
4567 #endif
4568 #if defined(HAS_UYVYTOARGBROW_AVX2)
4569   if (TestCpuFlag(kCpuHasAVX2)) {
4570     UYVYToARGBRow = UYVYToARGBRow_Any_AVX2;
4571     if (IS_ALIGNED(width, 32)) {
4572       UYVYToARGBRow = UYVYToARGBRow_AVX2;
4573     }
4574   }
4575 #endif
4576 #if defined(HAS_UYVYTOARGBROW_NEON)
4577   if (TestCpuFlag(kCpuHasNEON)) {
4578     UYVYToARGBRow = UYVYToARGBRow_Any_NEON;
4579     if (IS_ALIGNED(width, 8)) {
4580       UYVYToARGBRow = UYVYToARGBRow_NEON;
4581     }
4582   }
4583 #endif
4584 #if defined(HAS_UYVYTOARGBROW_MSA)
4585   if (TestCpuFlag(kCpuHasMSA)) {
4586     UYVYToARGBRow = UYVYToARGBRow_Any_MSA;
4587     if (IS_ALIGNED(width, 8)) {
4588       UYVYToARGBRow = UYVYToARGBRow_MSA;
4589     }
4590   }
4591 #endif
4592 #if defined(HAS_UYVYTOARGBROW_LSX)
4593   if (TestCpuFlag(kCpuHasLSX)) {
4594     UYVYToARGBRow = UYVYToARGBRow_Any_LSX;
4595     if (IS_ALIGNED(width, 8)) {
4596       UYVYToARGBRow = UYVYToARGBRow_LSX;
4597     }
4598   }
4599 #endif
4600   for (y = 0; y < height; ++y) {
4601     UYVYToARGBRow(src_uyvy, dst_argb, &kYuvI601Constants, width);
4602     src_uyvy += src_stride_uyvy;
4603     dst_argb += dst_stride_argb;
4604   }
4605   return 0;
4606 }
WeavePixels(const uint8_t * src_u,const uint8_t * src_v,int src_pixel_stride_uv,uint8_t * dst_uv,int width)4607 static void WeavePixels(const uint8_t* src_u,
4608                         const uint8_t* src_v,
4609                         int src_pixel_stride_uv,
4610                         uint8_t* dst_uv,
4611                         int width) {
4612   int i;
4613   for (i = 0; i < width; ++i) {
4614     dst_uv[0] = *src_u;
4615     dst_uv[1] = *src_v;
4616     dst_uv += 2;
4617     src_u += src_pixel_stride_uv;
4618     src_v += src_pixel_stride_uv;
4619   }
4620 }
4621 
4622 // Convert Android420 to ARGB with matrix.
4623 LIBYUV_API
Android420ToARGBMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,int src_pixel_stride_uv,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)4624 int Android420ToARGBMatrix(const uint8_t* src_y,
4625                            int src_stride_y,
4626                            const uint8_t* src_u,
4627                            int src_stride_u,
4628                            const uint8_t* src_v,
4629                            int src_stride_v,
4630                            int src_pixel_stride_uv,
4631                            uint8_t* dst_argb,
4632                            int dst_stride_argb,
4633                            const struct YuvConstants* yuvconstants,
4634                            int width,
4635                            int height) {
4636   int y;
4637   uint8_t* dst_uv;
4638   const ptrdiff_t vu_off = src_v - src_u;
4639   int halfwidth = (width + 1) >> 1;
4640   int halfheight = (height + 1) >> 1;
4641   assert(yuvconstants);
4642   if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
4643     return -1;
4644   }
4645   // Negative height means invert the image.
4646   if (height < 0) {
4647     height = -height;
4648     halfheight = (height + 1) >> 1;
4649     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
4650     dst_stride_argb = -dst_stride_argb;
4651   }
4652 
4653   // I420
4654   if (src_pixel_stride_uv == 1) {
4655     return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
4656                             src_stride_v, dst_argb, dst_stride_argb,
4657                             yuvconstants, width, height);
4658     // NV21
4659   }
4660   if (src_pixel_stride_uv == 2 && vu_off == -1 &&
4661       src_stride_u == src_stride_v) {
4662     return NV21ToARGBMatrix(src_y, src_stride_y, src_v, src_stride_v, dst_argb,
4663                             dst_stride_argb, yuvconstants, width, height);
4664     // NV12
4665   }
4666   if (src_pixel_stride_uv == 2 && vu_off == 1 && src_stride_u == src_stride_v) {
4667     return NV12ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, dst_argb,
4668                             dst_stride_argb, yuvconstants, width, height);
4669   }
4670 
4671   // General case fallback creates NV12
4672   align_buffer_64(plane_uv, halfwidth * 2 * halfheight);
4673   if (!plane_uv)
4674     return 1;
4675   dst_uv = plane_uv;
4676   for (y = 0; y < halfheight; ++y) {
4677     WeavePixels(src_u, src_v, src_pixel_stride_uv, dst_uv, halfwidth);
4678     src_u += src_stride_u;
4679     src_v += src_stride_v;
4680     dst_uv += halfwidth * 2;
4681   }
4682   NV12ToARGBMatrix(src_y, src_stride_y, plane_uv, halfwidth * 2, dst_argb,
4683                    dst_stride_argb, yuvconstants, width, height);
4684   free_aligned_buffer_64(plane_uv);
4685   return 0;
4686 }
4687 
4688 // Convert Android420 to ARGB.
4689 LIBYUV_API
Android420ToARGB(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,int src_pixel_stride_uv,uint8_t * dst_argb,int dst_stride_argb,int width,int height)4690 int Android420ToARGB(const uint8_t* src_y,
4691                      int src_stride_y,
4692                      const uint8_t* src_u,
4693                      int src_stride_u,
4694                      const uint8_t* src_v,
4695                      int src_stride_v,
4696                      int src_pixel_stride_uv,
4697                      uint8_t* dst_argb,
4698                      int dst_stride_argb,
4699                      int width,
4700                      int height) {
4701   return Android420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
4702                                 src_stride_v, src_pixel_stride_uv, dst_argb,
4703                                 dst_stride_argb, &kYuvI601Constants, width,
4704                                 height);
4705 }
4706 
4707 // Convert Android420 to ABGR.
4708 LIBYUV_API
Android420ToABGR(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,int src_pixel_stride_uv,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)4709 int Android420ToABGR(const uint8_t* src_y,
4710                      int src_stride_y,
4711                      const uint8_t* src_u,
4712                      int src_stride_u,
4713                      const uint8_t* src_v,
4714                      int src_stride_v,
4715                      int src_pixel_stride_uv,
4716                      uint8_t* dst_abgr,
4717                      int dst_stride_abgr,
4718                      int width,
4719                      int height) {
4720   return Android420ToARGBMatrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
4721                                 src_stride_u, src_pixel_stride_uv, dst_abgr,
4722                                 dst_stride_abgr, &kYvuI601Constants, width,
4723                                 height);
4724 }
4725 
4726 // Convert I422 to RGBA with matrix.
4727 LIBYUV_API
I422ToRGBAMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgba,int dst_stride_rgba,const struct YuvConstants * yuvconstants,int width,int height)4728 int I422ToRGBAMatrix(const uint8_t* src_y,
4729                      int src_stride_y,
4730                      const uint8_t* src_u,
4731                      int src_stride_u,
4732                      const uint8_t* src_v,
4733                      int src_stride_v,
4734                      uint8_t* dst_rgba,
4735                      int dst_stride_rgba,
4736                      const struct YuvConstants* yuvconstants,
4737                      int width,
4738                      int height) {
4739   int y;
4740   void (*I422ToRGBARow)(const uint8_t* y_buf, const uint8_t* u_buf,
4741                         const uint8_t* v_buf, uint8_t* rgb_buf,
4742                         const struct YuvConstants* yuvconstants, int width) =
4743       I422ToRGBARow_C;
4744   assert(yuvconstants);
4745   if (!src_y || !src_u || !src_v || !dst_rgba || width <= 0 || height == 0) {
4746     return -1;
4747   }
4748   // Negative height means invert the image.
4749   if (height < 0) {
4750     height = -height;
4751     dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba;
4752     dst_stride_rgba = -dst_stride_rgba;
4753   }
4754 #if defined(HAS_I422TORGBAROW_SSSE3)
4755   if (TestCpuFlag(kCpuHasSSSE3)) {
4756     I422ToRGBARow = I422ToRGBARow_Any_SSSE3;
4757     if (IS_ALIGNED(width, 8)) {
4758       I422ToRGBARow = I422ToRGBARow_SSSE3;
4759     }
4760   }
4761 #endif
4762 #if defined(HAS_I422TORGBAROW_AVX2)
4763   if (TestCpuFlag(kCpuHasAVX2)) {
4764     I422ToRGBARow = I422ToRGBARow_Any_AVX2;
4765     if (IS_ALIGNED(width, 16)) {
4766       I422ToRGBARow = I422ToRGBARow_AVX2;
4767     }
4768   }
4769 #endif
4770 #if defined(HAS_I422TORGBAROW_NEON)
4771   if (TestCpuFlag(kCpuHasNEON)) {
4772     I422ToRGBARow = I422ToRGBARow_Any_NEON;
4773     if (IS_ALIGNED(width, 8)) {
4774       I422ToRGBARow = I422ToRGBARow_NEON;
4775     }
4776   }
4777 #endif
4778 #if defined(HAS_I422TORGBAROW_MSA)
4779   if (TestCpuFlag(kCpuHasMSA)) {
4780     I422ToRGBARow = I422ToRGBARow_Any_MSA;
4781     if (IS_ALIGNED(width, 8)) {
4782       I422ToRGBARow = I422ToRGBARow_MSA;
4783     }
4784   }
4785 #endif
4786 #if defined(HAS_I422TORGBAROW_LSX)
4787   if (TestCpuFlag(kCpuHasLSX)) {
4788     I422ToRGBARow = I422ToRGBARow_Any_LSX;
4789     if (IS_ALIGNED(width, 16)) {
4790       I422ToRGBARow = I422ToRGBARow_LSX;
4791     }
4792   }
4793 #endif
4794 #if defined(HAS_I422TORGBAROW_LASX)
4795   if (TestCpuFlag(kCpuHasLASX)) {
4796     I422ToRGBARow = I422ToRGBARow_Any_LASX;
4797     if (IS_ALIGNED(width, 32)) {
4798       I422ToRGBARow = I422ToRGBARow_LASX;
4799     }
4800   }
4801 #endif
4802 #if defined(HAS_I422TORGBAROW_RVV)
4803   if (TestCpuFlag(kCpuHasRVV)) {
4804     I422ToRGBARow = I422ToRGBARow_RVV;
4805   }
4806 #endif
4807 
4808   for (y = 0; y < height; ++y) {
4809     I422ToRGBARow(src_y, src_u, src_v, dst_rgba, yuvconstants, width);
4810     dst_rgba += dst_stride_rgba;
4811     src_y += src_stride_y;
4812     src_u += src_stride_u;
4813     src_v += src_stride_v;
4814   }
4815   return 0;
4816 }
4817 
4818 // Convert I422 to RGBA.
4819 LIBYUV_API
I422ToRGBA(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgba,int dst_stride_rgba,int width,int height)4820 int I422ToRGBA(const uint8_t* src_y,
4821                int src_stride_y,
4822                const uint8_t* src_u,
4823                int src_stride_u,
4824                const uint8_t* src_v,
4825                int src_stride_v,
4826                uint8_t* dst_rgba,
4827                int dst_stride_rgba,
4828                int width,
4829                int height) {
4830   return I422ToRGBAMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
4831                           src_stride_v, dst_rgba, dst_stride_rgba,
4832                           &kYuvI601Constants, width, height);
4833 }
4834 
4835 // Convert I422 to BGRA.
4836 LIBYUV_API
I422ToBGRA(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_bgra,int dst_stride_bgra,int width,int height)4837 int I422ToBGRA(const uint8_t* src_y,
4838                int src_stride_y,
4839                const uint8_t* src_u,
4840                int src_stride_u,
4841                const uint8_t* src_v,
4842                int src_stride_v,
4843                uint8_t* dst_bgra,
4844                int dst_stride_bgra,
4845                int width,
4846                int height) {
4847   return I422ToRGBAMatrix(src_y, src_stride_y, src_v,
4848                           src_stride_v,  // Swap U and V
4849                           src_u, src_stride_u, dst_bgra, dst_stride_bgra,
4850                           &kYvuI601Constants,  // Use Yvu matrix
4851                           width, height);
4852 }
4853 
4854 // Convert NV12 to RGB565 with matrix.
4855 LIBYUV_API
NV12ToRGB565Matrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_rgb565,int dst_stride_rgb565,const struct YuvConstants * yuvconstants,int width,int height)4856 int NV12ToRGB565Matrix(const uint8_t* src_y,
4857                        int src_stride_y,
4858                        const uint8_t* src_uv,
4859                        int src_stride_uv,
4860                        uint8_t* dst_rgb565,
4861                        int dst_stride_rgb565,
4862                        const struct YuvConstants* yuvconstants,
4863                        int width,
4864                        int height) {
4865   int y;
4866   void (*NV12ToRGB565Row)(
4867       const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
4868       const struct YuvConstants* yuvconstants, int width) = NV12ToRGB565Row_C;
4869   assert(yuvconstants);
4870   if (!src_y || !src_uv || !dst_rgb565 || width <= 0 || height == 0) {
4871     return -1;
4872   }
4873   // Negative height means invert the image.
4874   if (height < 0) {
4875     height = -height;
4876     dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
4877     dst_stride_rgb565 = -dst_stride_rgb565;
4878   }
4879 #if defined(HAS_NV12TORGB565ROW_SSSE3)
4880   if (TestCpuFlag(kCpuHasSSSE3)) {
4881     NV12ToRGB565Row = NV12ToRGB565Row_Any_SSSE3;
4882     if (IS_ALIGNED(width, 8)) {
4883       NV12ToRGB565Row = NV12ToRGB565Row_SSSE3;
4884     }
4885   }
4886 #endif
4887 #if defined(HAS_NV12TORGB565ROW_AVX2)
4888   if (TestCpuFlag(kCpuHasAVX2)) {
4889     NV12ToRGB565Row = NV12ToRGB565Row_Any_AVX2;
4890     if (IS_ALIGNED(width, 16)) {
4891       NV12ToRGB565Row = NV12ToRGB565Row_AVX2;
4892     }
4893   }
4894 #endif
4895 #if defined(HAS_NV12TORGB565ROW_NEON)
4896   if (TestCpuFlag(kCpuHasNEON)) {
4897     NV12ToRGB565Row = NV12ToRGB565Row_Any_NEON;
4898     if (IS_ALIGNED(width, 8)) {
4899       NV12ToRGB565Row = NV12ToRGB565Row_NEON;
4900     }
4901   }
4902 #endif
4903 #if defined(HAS_NV12TORGB565ROW_MSA)
4904   if (TestCpuFlag(kCpuHasMSA)) {
4905     NV12ToRGB565Row = NV12ToRGB565Row_Any_MSA;
4906     if (IS_ALIGNED(width, 8)) {
4907       NV12ToRGB565Row = NV12ToRGB565Row_MSA;
4908     }
4909   }
4910 #endif
4911 #if defined(HAS_NV12TORGB565ROW_LSX)
4912   if (TestCpuFlag(kCpuHasLSX)) {
4913     NV12ToRGB565Row = NV12ToRGB565Row_Any_LSX;
4914     if (IS_ALIGNED(width, 8)) {
4915       NV12ToRGB565Row = NV12ToRGB565Row_LSX;
4916     }
4917   }
4918 #endif
4919 #if defined(HAS_NV12TORGB565ROW_LASX)
4920   if (TestCpuFlag(kCpuHasLASX)) {
4921     NV12ToRGB565Row = NV12ToRGB565Row_Any_LASX;
4922     if (IS_ALIGNED(width, 16)) {
4923       NV12ToRGB565Row = NV12ToRGB565Row_LASX;
4924     }
4925   }
4926 #endif
4927 
4928   for (y = 0; y < height; ++y) {
4929     NV12ToRGB565Row(src_y, src_uv, dst_rgb565, yuvconstants, width);
4930     dst_rgb565 += dst_stride_rgb565;
4931     src_y += src_stride_y;
4932     if (y & 1) {
4933       src_uv += src_stride_uv;
4934     }
4935   }
4936   return 0;
4937 }
4938 
4939 // Convert NV12 to RGB565.
4940 LIBYUV_API
NV12ToRGB565(const uint8_t * src_y,int src_stride_y,const uint8_t * src_uv,int src_stride_uv,uint8_t * dst_rgb565,int dst_stride_rgb565,int width,int height)4941 int NV12ToRGB565(const uint8_t* src_y,
4942                  int src_stride_y,
4943                  const uint8_t* src_uv,
4944                  int src_stride_uv,
4945                  uint8_t* dst_rgb565,
4946                  int dst_stride_rgb565,
4947                  int width,
4948                  int height) {
4949   return NV12ToRGB565Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
4950                             dst_rgb565, dst_stride_rgb565, &kYuvI601Constants,
4951                             width, height);
4952 }
4953 
4954 // Convert I422 to RGBA with matrix.
4955 LIBYUV_API
I420ToRGBAMatrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgba,int dst_stride_rgba,const struct YuvConstants * yuvconstants,int width,int height)4956 int I420ToRGBAMatrix(const uint8_t* src_y,
4957                      int src_stride_y,
4958                      const uint8_t* src_u,
4959                      int src_stride_u,
4960                      const uint8_t* src_v,
4961                      int src_stride_v,
4962                      uint8_t* dst_rgba,
4963                      int dst_stride_rgba,
4964                      const struct YuvConstants* yuvconstants,
4965                      int width,
4966                      int height) {
4967   int y;
4968   void (*I422ToRGBARow)(const uint8_t* y_buf, const uint8_t* u_buf,
4969                         const uint8_t* v_buf, uint8_t* rgb_buf,
4970                         const struct YuvConstants* yuvconstants, int width) =
4971       I422ToRGBARow_C;
4972   assert(yuvconstants);
4973   if (!src_y || !src_u || !src_v || !dst_rgba || width <= 0 || height == 0) {
4974     return -1;
4975   }
4976   // Negative height means invert the image.
4977   if (height < 0) {
4978     height = -height;
4979     dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba;
4980     dst_stride_rgba = -dst_stride_rgba;
4981   }
4982 #if defined(HAS_I422TORGBAROW_SSSE3)
4983   if (TestCpuFlag(kCpuHasSSSE3)) {
4984     I422ToRGBARow = I422ToRGBARow_Any_SSSE3;
4985     if (IS_ALIGNED(width, 8)) {
4986       I422ToRGBARow = I422ToRGBARow_SSSE3;
4987     }
4988   }
4989 #endif
4990 #if defined(HAS_I422TORGBAROW_AVX2)
4991   if (TestCpuFlag(kCpuHasAVX2)) {
4992     I422ToRGBARow = I422ToRGBARow_Any_AVX2;
4993     if (IS_ALIGNED(width, 16)) {
4994       I422ToRGBARow = I422ToRGBARow_AVX2;
4995     }
4996   }
4997 #endif
4998 #if defined(HAS_I422TORGBAROW_NEON)
4999   if (TestCpuFlag(kCpuHasNEON)) {
5000     I422ToRGBARow = I422ToRGBARow_Any_NEON;
5001     if (IS_ALIGNED(width, 8)) {
5002       I422ToRGBARow = I422ToRGBARow_NEON;
5003     }
5004   }
5005 #endif
5006 #if defined(HAS_I422TORGBAROW_MSA)
5007   if (TestCpuFlag(kCpuHasMSA)) {
5008     I422ToRGBARow = I422ToRGBARow_Any_MSA;
5009     if (IS_ALIGNED(width, 8)) {
5010       I422ToRGBARow = I422ToRGBARow_MSA;
5011     }
5012   }
5013 #endif
5014 #if defined(HAS_I422TORGBAROW_LSX)
5015   if (TestCpuFlag(kCpuHasLSX)) {
5016     I422ToRGBARow = I422ToRGBARow_Any_LSX;
5017     if (IS_ALIGNED(width, 16)) {
5018       I422ToRGBARow = I422ToRGBARow_LSX;
5019     }
5020   }
5021 #endif
5022 #if defined(HAS_I422TORGBAROW_LASX)
5023   if (TestCpuFlag(kCpuHasLASX)) {
5024     I422ToRGBARow = I422ToRGBARow_Any_LASX;
5025     if (IS_ALIGNED(width, 32)) {
5026       I422ToRGBARow = I422ToRGBARow_LASX;
5027     }
5028   }
5029 #endif
5030 #if defined(HAS_I422TORGBAROW_RVV)
5031   if (TestCpuFlag(kCpuHasRVV)) {
5032     I422ToRGBARow = I422ToRGBARow_RVV;
5033   }
5034 #endif
5035 
5036   for (y = 0; y < height; ++y) {
5037     I422ToRGBARow(src_y, src_u, src_v, dst_rgba, yuvconstants, width);
5038     dst_rgba += dst_stride_rgba;
5039     src_y += src_stride_y;
5040     if (y & 1) {
5041       src_u += src_stride_u;
5042       src_v += src_stride_v;
5043     }
5044   }
5045   return 0;
5046 }
5047 
5048 // Convert I420 to RGBA.
5049 LIBYUV_API
I420ToRGBA(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgba,int dst_stride_rgba,int width,int height)5050 int I420ToRGBA(const uint8_t* src_y,
5051                int src_stride_y,
5052                const uint8_t* src_u,
5053                int src_stride_u,
5054                const uint8_t* src_v,
5055                int src_stride_v,
5056                uint8_t* dst_rgba,
5057                int dst_stride_rgba,
5058                int width,
5059                int height) {
5060   return I420ToRGBAMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5061                           src_stride_v, dst_rgba, dst_stride_rgba,
5062                           &kYuvI601Constants, width, height);
5063 }
5064 
5065 // Convert I420 to BGRA.
5066 LIBYUV_API
I420ToBGRA(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_bgra,int dst_stride_bgra,int width,int height)5067 int I420ToBGRA(const uint8_t* src_y,
5068                int src_stride_y,
5069                const uint8_t* src_u,
5070                int src_stride_u,
5071                const uint8_t* src_v,
5072                int src_stride_v,
5073                uint8_t* dst_bgra,
5074                int dst_stride_bgra,
5075                int width,
5076                int height) {
5077   return I420ToRGBAMatrix(src_y, src_stride_y, src_v,
5078                           src_stride_v,  // Swap U and V
5079                           src_u, src_stride_u, dst_bgra, dst_stride_bgra,
5080                           &kYvuI601Constants,  // Use Yvu matrix
5081                           width, height);
5082 }
5083 
5084 // Convert I420 to RGB24 with matrix.
5085 LIBYUV_API
I420ToRGB24Matrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgb24,int dst_stride_rgb24,const struct YuvConstants * yuvconstants,int width,int height)5086 int I420ToRGB24Matrix(const uint8_t* src_y,
5087                       int src_stride_y,
5088                       const uint8_t* src_u,
5089                       int src_stride_u,
5090                       const uint8_t* src_v,
5091                       int src_stride_v,
5092                       uint8_t* dst_rgb24,
5093                       int dst_stride_rgb24,
5094                       const struct YuvConstants* yuvconstants,
5095                       int width,
5096                       int height) {
5097   int y;
5098   void (*I422ToRGB24Row)(const uint8_t* y_buf, const uint8_t* u_buf,
5099                          const uint8_t* v_buf, uint8_t* rgb_buf,
5100                          const struct YuvConstants* yuvconstants, int width) =
5101       I422ToRGB24Row_C;
5102   assert(yuvconstants);
5103   if (!src_y || !src_u || !src_v || !dst_rgb24 || width <= 0 || height == 0) {
5104     return -1;
5105   }
5106   // Negative height means invert the image.
5107   if (height < 0) {
5108     height = -height;
5109     dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
5110     dst_stride_rgb24 = -dst_stride_rgb24;
5111   }
5112 #if defined(HAS_I422TORGB24ROW_SSSE3)
5113   if (TestCpuFlag(kCpuHasSSSE3)) {
5114     I422ToRGB24Row = I422ToRGB24Row_Any_SSSE3;
5115     if (IS_ALIGNED(width, 16)) {
5116       I422ToRGB24Row = I422ToRGB24Row_SSSE3;
5117     }
5118   }
5119 #endif
5120 #if defined(HAS_I422TORGB24ROW_AVX2)
5121   if (TestCpuFlag(kCpuHasAVX2)) {
5122     I422ToRGB24Row = I422ToRGB24Row_Any_AVX2;
5123     if (IS_ALIGNED(width, 32)) {
5124       I422ToRGB24Row = I422ToRGB24Row_AVX2;
5125     }
5126   }
5127 #endif
5128 #if defined(HAS_I422TORGB24ROW_NEON)
5129   if (TestCpuFlag(kCpuHasNEON)) {
5130     I422ToRGB24Row = I422ToRGB24Row_Any_NEON;
5131     if (IS_ALIGNED(width, 8)) {
5132       I422ToRGB24Row = I422ToRGB24Row_NEON;
5133     }
5134   }
5135 #endif
5136 #if defined(HAS_I422TORGB24ROW_MSA)
5137   if (TestCpuFlag(kCpuHasMSA)) {
5138     I422ToRGB24Row = I422ToRGB24Row_Any_MSA;
5139     if (IS_ALIGNED(width, 16)) {
5140       I422ToRGB24Row = I422ToRGB24Row_MSA;
5141     }
5142   }
5143 #endif
5144 #if defined(HAS_I422TORGB24ROW_LSX)
5145   if (TestCpuFlag(kCpuHasLSX)) {
5146     I422ToRGB24Row = I422ToRGB24Row_Any_LSX;
5147     if (IS_ALIGNED(width, 16)) {
5148       I422ToRGB24Row = I422ToRGB24Row_LSX;
5149     }
5150   }
5151 #endif
5152 #if defined(HAS_I422TORGB24ROW_LASX)
5153   if (TestCpuFlag(kCpuHasLASX)) {
5154     I422ToRGB24Row = I422ToRGB24Row_Any_LASX;
5155     if (IS_ALIGNED(width, 32)) {
5156       I422ToRGB24Row = I422ToRGB24Row_LASX;
5157     }
5158   }
5159 #endif
5160 #if defined(HAS_I422TORGB24ROW_RVV)
5161   if (TestCpuFlag(kCpuHasRVV)) {
5162     I422ToRGB24Row = I422ToRGB24Row_RVV;
5163   }
5164 #endif
5165 
5166   for (y = 0; y < height; ++y) {
5167     I422ToRGB24Row(src_y, src_u, src_v, dst_rgb24, yuvconstants, width);
5168     dst_rgb24 += dst_stride_rgb24;
5169     src_y += src_stride_y;
5170     if (y & 1) {
5171       src_u += src_stride_u;
5172       src_v += src_stride_v;
5173     }
5174   }
5175   return 0;
5176 }
5177 
5178 // Convert I420 to RGB24.
5179 LIBYUV_API
I420ToRGB24(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgb24,int dst_stride_rgb24,int width,int height)5180 int I420ToRGB24(const uint8_t* src_y,
5181                 int src_stride_y,
5182                 const uint8_t* src_u,
5183                 int src_stride_u,
5184                 const uint8_t* src_v,
5185                 int src_stride_v,
5186                 uint8_t* dst_rgb24,
5187                 int dst_stride_rgb24,
5188                 int width,
5189                 int height) {
5190   return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5191                            src_stride_v, dst_rgb24, dst_stride_rgb24,
5192                            &kYuvI601Constants, width, height);
5193 }
5194 
5195 // Convert I420 to RAW.
5196 LIBYUV_API
I420ToRAW(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_raw,int dst_stride_raw,int width,int height)5197 int I420ToRAW(const uint8_t* src_y,
5198               int src_stride_y,
5199               const uint8_t* src_u,
5200               int src_stride_u,
5201               const uint8_t* src_v,
5202               int src_stride_v,
5203               uint8_t* dst_raw,
5204               int dst_stride_raw,
5205               int width,
5206               int height) {
5207   return I420ToRGB24Matrix(src_y, src_stride_y, src_v,
5208                            src_stride_v,  // Swap U and V
5209                            src_u, src_stride_u, dst_raw, dst_stride_raw,
5210                            &kYvuI601Constants,  // Use Yvu matrix
5211                            width, height);
5212 }
5213 
5214 // Convert J420 to RGB24.
5215 LIBYUV_API
J420ToRGB24(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgb24,int dst_stride_rgb24,int width,int height)5216 int J420ToRGB24(const uint8_t* src_y,
5217                 int src_stride_y,
5218                 const uint8_t* src_u,
5219                 int src_stride_u,
5220                 const uint8_t* src_v,
5221                 int src_stride_v,
5222                 uint8_t* dst_rgb24,
5223                 int dst_stride_rgb24,
5224                 int width,
5225                 int height) {
5226   return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5227                            src_stride_v, dst_rgb24, dst_stride_rgb24,
5228                            &kYuvJPEGConstants, width, height);
5229 }
5230 
5231 // Convert J420 to RAW.
5232 LIBYUV_API
J420ToRAW(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_raw,int dst_stride_raw,int width,int height)5233 int J420ToRAW(const uint8_t* src_y,
5234               int src_stride_y,
5235               const uint8_t* src_u,
5236               int src_stride_u,
5237               const uint8_t* src_v,
5238               int src_stride_v,
5239               uint8_t* dst_raw,
5240               int dst_stride_raw,
5241               int width,
5242               int height) {
5243   return I420ToRGB24Matrix(src_y, src_stride_y, src_v,
5244                            src_stride_v,  // Swap U and V
5245                            src_u, src_stride_u, dst_raw, dst_stride_raw,
5246                            &kYvuJPEGConstants,  // Use Yvu matrix
5247                            width, height);
5248 }
5249 
5250 // Convert H420 to RGB24.
5251 LIBYUV_API
H420ToRGB24(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgb24,int dst_stride_rgb24,int width,int height)5252 int H420ToRGB24(const uint8_t* src_y,
5253                 int src_stride_y,
5254                 const uint8_t* src_u,
5255                 int src_stride_u,
5256                 const uint8_t* src_v,
5257                 int src_stride_v,
5258                 uint8_t* dst_rgb24,
5259                 int dst_stride_rgb24,
5260                 int width,
5261                 int height) {
5262   return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5263                            src_stride_v, dst_rgb24, dst_stride_rgb24,
5264                            &kYuvH709Constants, width, height);
5265 }
5266 
5267 // Convert H420 to RAW.
5268 LIBYUV_API
H420ToRAW(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_raw,int dst_stride_raw,int width,int height)5269 int H420ToRAW(const uint8_t* src_y,
5270               int src_stride_y,
5271               const uint8_t* src_u,
5272               int src_stride_u,
5273               const uint8_t* src_v,
5274               int src_stride_v,
5275               uint8_t* dst_raw,
5276               int dst_stride_raw,
5277               int width,
5278               int height) {
5279   return I420ToRGB24Matrix(src_y, src_stride_y, src_v,
5280                            src_stride_v,  // Swap U and V
5281                            src_u, src_stride_u, dst_raw, dst_stride_raw,
5282                            &kYvuH709Constants,  // Use Yvu matrix
5283                            width, height);
5284 }
5285 
5286 // Convert I422 to RGB24 with matrix.
5287 LIBYUV_API
I422ToRGB24Matrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgb24,int dst_stride_rgb24,const struct YuvConstants * yuvconstants,int width,int height)5288 int I422ToRGB24Matrix(const uint8_t* src_y,
5289                       int src_stride_y,
5290                       const uint8_t* src_u,
5291                       int src_stride_u,
5292                       const uint8_t* src_v,
5293                       int src_stride_v,
5294                       uint8_t* dst_rgb24,
5295                       int dst_stride_rgb24,
5296                       const struct YuvConstants* yuvconstants,
5297                       int width,
5298                       int height) {
5299   int y;
5300   void (*I422ToRGB24Row)(const uint8_t* y_buf, const uint8_t* u_buf,
5301                          const uint8_t* v_buf, uint8_t* rgb_buf,
5302                          const struct YuvConstants* yuvconstants, int width) =
5303       I422ToRGB24Row_C;
5304   assert(yuvconstants);
5305   if (!src_y || !src_u || !src_v || !dst_rgb24 || width <= 0 || height == 0) {
5306     return -1;
5307   }
5308   // Negative height means invert the image.
5309   if (height < 0) {
5310     height = -height;
5311     dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
5312     dst_stride_rgb24 = -dst_stride_rgb24;
5313   }
5314 #if defined(HAS_I422TORGB24ROW_SSSE3)
5315   if (TestCpuFlag(kCpuHasSSSE3)) {
5316     I422ToRGB24Row = I422ToRGB24Row_Any_SSSE3;
5317     if (IS_ALIGNED(width, 16)) {
5318       I422ToRGB24Row = I422ToRGB24Row_SSSE3;
5319     }
5320   }
5321 #endif
5322 #if defined(HAS_I422TORGB24ROW_AVX2)
5323   if (TestCpuFlag(kCpuHasAVX2)) {
5324     I422ToRGB24Row = I422ToRGB24Row_Any_AVX2;
5325     if (IS_ALIGNED(width, 32)) {
5326       I422ToRGB24Row = I422ToRGB24Row_AVX2;
5327     }
5328   }
5329 #endif
5330 #if defined(HAS_I422TORGB24ROW_NEON)
5331   if (TestCpuFlag(kCpuHasNEON)) {
5332     I422ToRGB24Row = I422ToRGB24Row_Any_NEON;
5333     if (IS_ALIGNED(width, 8)) {
5334       I422ToRGB24Row = I422ToRGB24Row_NEON;
5335     }
5336   }
5337 #endif
5338 #if defined(HAS_I422TORGB24ROW_MSA)
5339   if (TestCpuFlag(kCpuHasMSA)) {
5340     I422ToRGB24Row = I422ToRGB24Row_Any_MSA;
5341     if (IS_ALIGNED(width, 16)) {
5342       I422ToRGB24Row = I422ToRGB24Row_MSA;
5343     }
5344   }
5345 #endif
5346 #if defined(HAS_I422TORGB24ROW_LSX)
5347   if (TestCpuFlag(kCpuHasLSX)) {
5348     I422ToRGB24Row = I422ToRGB24Row_Any_LSX;
5349     if (IS_ALIGNED(width, 16)) {
5350       I422ToRGB24Row = I422ToRGB24Row_LSX;
5351     }
5352   }
5353 #endif
5354 #if defined(HAS_I422TORGB24ROW_LASX)
5355   if (TestCpuFlag(kCpuHasLASX)) {
5356     I422ToRGB24Row = I422ToRGB24Row_Any_LASX;
5357     if (IS_ALIGNED(width, 32)) {
5358       I422ToRGB24Row = I422ToRGB24Row_LASX;
5359     }
5360   }
5361 #endif
5362 #if defined(HAS_I422TORGB24ROW_RVV)
5363   if (TestCpuFlag(kCpuHasRVV)) {
5364     I422ToRGB24Row = I422ToRGB24Row_RVV;
5365   }
5366 #endif
5367 
5368   for (y = 0; y < height; ++y) {
5369     I422ToRGB24Row(src_y, src_u, src_v, dst_rgb24, yuvconstants, width);
5370     dst_rgb24 += dst_stride_rgb24;
5371     src_y += src_stride_y;
5372     src_u += src_stride_u;
5373     src_v += src_stride_v;
5374   }
5375   return 0;
5376 }
5377 
5378 // Convert I422 to RGB24.
5379 LIBYUV_API
I422ToRGB24(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgb24,int dst_stride_rgb24,int width,int height)5380 int I422ToRGB24(const uint8_t* src_y,
5381                 int src_stride_y,
5382                 const uint8_t* src_u,
5383                 int src_stride_u,
5384                 const uint8_t* src_v,
5385                 int src_stride_v,
5386                 uint8_t* dst_rgb24,
5387                 int dst_stride_rgb24,
5388                 int width,
5389                 int height) {
5390   return I422ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5391                            src_stride_v, dst_rgb24, dst_stride_rgb24,
5392                            &kYuvI601Constants, width, height);
5393 }
5394 
5395 // Convert I422 to RAW.
5396 LIBYUV_API
I422ToRAW(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_raw,int dst_stride_raw,int width,int height)5397 int I422ToRAW(const uint8_t* src_y,
5398               int src_stride_y,
5399               const uint8_t* src_u,
5400               int src_stride_u,
5401               const uint8_t* src_v,
5402               int src_stride_v,
5403               uint8_t* dst_raw,
5404               int dst_stride_raw,
5405               int width,
5406               int height) {
5407   return I422ToRGB24Matrix(src_y, src_stride_y, src_v,
5408                            src_stride_v,  // Swap U and V
5409                            src_u, src_stride_u, dst_raw, dst_stride_raw,
5410                            &kYvuI601Constants,  // Use Yvu matrix
5411                            width, height);
5412 }
5413 
5414 // Convert I420 to ARGB1555.
5415 LIBYUV_API
I420ToARGB1555(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb1555,int dst_stride_argb1555,int width,int height)5416 int I420ToARGB1555(const uint8_t* src_y,
5417                    int src_stride_y,
5418                    const uint8_t* src_u,
5419                    int src_stride_u,
5420                    const uint8_t* src_v,
5421                    int src_stride_v,
5422                    uint8_t* dst_argb1555,
5423                    int dst_stride_argb1555,
5424                    int width,
5425                    int height) {
5426   int y;
5427   void (*I422ToARGB1555Row)(const uint8_t* y_buf, const uint8_t* u_buf,
5428                             const uint8_t* v_buf, uint8_t* rgb_buf,
5429                             const struct YuvConstants* yuvconstants,
5430                             int width) = I422ToARGB1555Row_C;
5431   if (!src_y || !src_u || !src_v || !dst_argb1555 || width <= 0 ||
5432       height == 0) {
5433     return -1;
5434   }
5435   // Negative height means invert the image.
5436   if (height < 0) {
5437     height = -height;
5438     dst_argb1555 = dst_argb1555 + (height - 1) * dst_stride_argb1555;
5439     dst_stride_argb1555 = -dst_stride_argb1555;
5440   }
5441 #if defined(HAS_I422TOARGB1555ROW_SSSE3)
5442   if (TestCpuFlag(kCpuHasSSSE3)) {
5443     I422ToARGB1555Row = I422ToARGB1555Row_Any_SSSE3;
5444     if (IS_ALIGNED(width, 8)) {
5445       I422ToARGB1555Row = I422ToARGB1555Row_SSSE3;
5446     }
5447   }
5448 #endif
5449 #if defined(HAS_I422TOARGB1555ROW_AVX2)
5450   if (TestCpuFlag(kCpuHasAVX2)) {
5451     I422ToARGB1555Row = I422ToARGB1555Row_Any_AVX2;
5452     if (IS_ALIGNED(width, 16)) {
5453       I422ToARGB1555Row = I422ToARGB1555Row_AVX2;
5454     }
5455   }
5456 #endif
5457 #if defined(HAS_I422TOARGB1555ROW_NEON)
5458   if (TestCpuFlag(kCpuHasNEON)) {
5459     I422ToARGB1555Row = I422ToARGB1555Row_Any_NEON;
5460     if (IS_ALIGNED(width, 8)) {
5461       I422ToARGB1555Row = I422ToARGB1555Row_NEON;
5462     }
5463   }
5464 #endif
5465 #if defined(HAS_I422TOARGB1555ROW_MSA)
5466   if (TestCpuFlag(kCpuHasMSA)) {
5467     I422ToARGB1555Row = I422ToARGB1555Row_Any_MSA;
5468     if (IS_ALIGNED(width, 8)) {
5469       I422ToARGB1555Row = I422ToARGB1555Row_MSA;
5470     }
5471   }
5472 #endif
5473 #if defined(HAS_I422TOARGB1555ROW_LSX)
5474   if (TestCpuFlag(kCpuHasLSX)) {
5475     I422ToARGB1555Row = I422ToARGB1555Row_Any_LSX;
5476     if (IS_ALIGNED(width, 16)) {
5477       I422ToARGB1555Row = I422ToARGB1555Row_LSX;
5478     }
5479   }
5480 #endif
5481 #if defined(HAS_I422TOARGB1555ROW_LASX)
5482   if (TestCpuFlag(kCpuHasLASX)) {
5483     I422ToARGB1555Row = I422ToARGB1555Row_Any_LASX;
5484     if (IS_ALIGNED(width, 8)) {
5485       I422ToARGB1555Row = I422ToARGB1555Row_LASX;
5486     }
5487   }
5488 #endif
5489 
5490   for (y = 0; y < height; ++y) {
5491     I422ToARGB1555Row(src_y, src_u, src_v, dst_argb1555, &kYuvI601Constants,
5492                       width);
5493     dst_argb1555 += dst_stride_argb1555;
5494     src_y += src_stride_y;
5495     if (y & 1) {
5496       src_u += src_stride_u;
5497       src_v += src_stride_v;
5498     }
5499   }
5500   return 0;
5501 }
5502 
5503 // Convert I420 to ARGB4444.
5504 LIBYUV_API
I420ToARGB4444(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb4444,int dst_stride_argb4444,int width,int height)5505 int I420ToARGB4444(const uint8_t* src_y,
5506                    int src_stride_y,
5507                    const uint8_t* src_u,
5508                    int src_stride_u,
5509                    const uint8_t* src_v,
5510                    int src_stride_v,
5511                    uint8_t* dst_argb4444,
5512                    int dst_stride_argb4444,
5513                    int width,
5514                    int height) {
5515   int y;
5516   void (*I422ToARGB4444Row)(const uint8_t* y_buf, const uint8_t* u_buf,
5517                             const uint8_t* v_buf, uint8_t* rgb_buf,
5518                             const struct YuvConstants* yuvconstants,
5519                             int width) = I422ToARGB4444Row_C;
5520   if (!src_y || !src_u || !src_v || !dst_argb4444 || width <= 0 ||
5521       height == 0) {
5522     return -1;
5523   }
5524   // Negative height means invert the image.
5525   if (height < 0) {
5526     height = -height;
5527     dst_argb4444 = dst_argb4444 + (height - 1) * dst_stride_argb4444;
5528     dst_stride_argb4444 = -dst_stride_argb4444;
5529   }
5530 #if defined(HAS_I422TOARGB4444ROW_SSSE3)
5531   if (TestCpuFlag(kCpuHasSSSE3)) {
5532     I422ToARGB4444Row = I422ToARGB4444Row_Any_SSSE3;
5533     if (IS_ALIGNED(width, 8)) {
5534       I422ToARGB4444Row = I422ToARGB4444Row_SSSE3;
5535     }
5536   }
5537 #endif
5538 #if defined(HAS_I422TOARGB4444ROW_AVX2)
5539   if (TestCpuFlag(kCpuHasAVX2)) {
5540     I422ToARGB4444Row = I422ToARGB4444Row_Any_AVX2;
5541     if (IS_ALIGNED(width, 16)) {
5542       I422ToARGB4444Row = I422ToARGB4444Row_AVX2;
5543     }
5544   }
5545 #endif
5546 #if defined(HAS_I422TOARGB4444ROW_NEON)
5547   if (TestCpuFlag(kCpuHasNEON)) {
5548     I422ToARGB4444Row = I422ToARGB4444Row_Any_NEON;
5549     if (IS_ALIGNED(width, 8)) {
5550       I422ToARGB4444Row = I422ToARGB4444Row_NEON;
5551     }
5552   }
5553 #endif
5554 #if defined(HAS_I422TOARGB4444ROW_MSA)
5555   if (TestCpuFlag(kCpuHasMSA)) {
5556     I422ToARGB4444Row = I422ToARGB4444Row_Any_MSA;
5557     if (IS_ALIGNED(width, 8)) {
5558       I422ToARGB4444Row = I422ToARGB4444Row_MSA;
5559     }
5560   }
5561 #endif
5562 #if defined(HAS_I422TOARGB4444ROW_LSX)
5563   if (TestCpuFlag(kCpuHasLSX)) {
5564     I422ToARGB4444Row = I422ToARGB4444Row_Any_LSX;
5565     if (IS_ALIGNED(width, 16)) {
5566       I422ToARGB4444Row = I422ToARGB4444Row_LSX;
5567     }
5568   }
5569 #endif
5570 #if defined(HAS_I422TOARGB4444ROW_LASX)
5571   if (TestCpuFlag(kCpuHasLASX)) {
5572     I422ToARGB4444Row = I422ToARGB4444Row_Any_LASX;
5573     if (IS_ALIGNED(width, 8)) {
5574       I422ToARGB4444Row = I422ToARGB4444Row_LASX;
5575     }
5576   }
5577 #endif
5578 
5579   for (y = 0; y < height; ++y) {
5580     I422ToARGB4444Row(src_y, src_u, src_v, dst_argb4444, &kYuvI601Constants,
5581                       width);
5582     dst_argb4444 += dst_stride_argb4444;
5583     src_y += src_stride_y;
5584     if (y & 1) {
5585       src_u += src_stride_u;
5586       src_v += src_stride_v;
5587     }
5588   }
5589   return 0;
5590 }
5591 
5592 // Convert I420 to RGB565 with specified color matrix.
5593 LIBYUV_API
I420ToRGB565Matrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgb565,int dst_stride_rgb565,const struct YuvConstants * yuvconstants,int width,int height)5594 int I420ToRGB565Matrix(const uint8_t* src_y,
5595                        int src_stride_y,
5596                        const uint8_t* src_u,
5597                        int src_stride_u,
5598                        const uint8_t* src_v,
5599                        int src_stride_v,
5600                        uint8_t* dst_rgb565,
5601                        int dst_stride_rgb565,
5602                        const struct YuvConstants* yuvconstants,
5603                        int width,
5604                        int height) {
5605   int y;
5606   void (*I422ToRGB565Row)(const uint8_t* y_buf, const uint8_t* u_buf,
5607                           const uint8_t* v_buf, uint8_t* rgb_buf,
5608                           const struct YuvConstants* yuvconstants, int width) =
5609       I422ToRGB565Row_C;
5610   assert(yuvconstants);
5611   if (!src_y || !src_u || !src_v || !dst_rgb565 || width <= 0 || height == 0) {
5612     return -1;
5613   }
5614   // Negative height means invert the image.
5615   if (height < 0) {
5616     height = -height;
5617     dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
5618     dst_stride_rgb565 = -dst_stride_rgb565;
5619   }
5620 #if defined(HAS_I422TORGB565ROW_SSSE3)
5621   if (TestCpuFlag(kCpuHasSSSE3)) {
5622     I422ToRGB565Row = I422ToRGB565Row_Any_SSSE3;
5623     if (IS_ALIGNED(width, 8)) {
5624       I422ToRGB565Row = I422ToRGB565Row_SSSE3;
5625     }
5626   }
5627 #endif
5628 #if defined(HAS_I422TORGB565ROW_AVX2)
5629   if (TestCpuFlag(kCpuHasAVX2)) {
5630     I422ToRGB565Row = I422ToRGB565Row_Any_AVX2;
5631     if (IS_ALIGNED(width, 16)) {
5632       I422ToRGB565Row = I422ToRGB565Row_AVX2;
5633     }
5634   }
5635 #endif
5636 #if defined(HAS_I422TORGB565ROW_NEON)
5637   if (TestCpuFlag(kCpuHasNEON)) {
5638     I422ToRGB565Row = I422ToRGB565Row_Any_NEON;
5639     if (IS_ALIGNED(width, 8)) {
5640       I422ToRGB565Row = I422ToRGB565Row_NEON;
5641     }
5642   }
5643 #endif
5644 #if defined(HAS_I422TORGB565ROW_MSA)
5645   if (TestCpuFlag(kCpuHasMSA)) {
5646     I422ToRGB565Row = I422ToRGB565Row_Any_MSA;
5647     if (IS_ALIGNED(width, 8)) {
5648       I422ToRGB565Row = I422ToRGB565Row_MSA;
5649     }
5650   }
5651 #endif
5652 #if defined(HAS_I422TORGB565ROW_LSX)
5653   if (TestCpuFlag(kCpuHasLSX)) {
5654     I422ToRGB565Row = I422ToRGB565Row_Any_LSX;
5655     if (IS_ALIGNED(width, 16)) {
5656       I422ToRGB565Row = I422ToRGB565Row_LSX;
5657     }
5658   }
5659 #endif
5660 #if defined(HAS_I422TORGB565ROW_LASX)
5661   if (TestCpuFlag(kCpuHasLASX)) {
5662     I422ToRGB565Row = I422ToRGB565Row_Any_LASX;
5663     if (IS_ALIGNED(width, 32)) {
5664       I422ToRGB565Row = I422ToRGB565Row_LASX;
5665     }
5666   }
5667 #endif
5668 
5669   for (y = 0; y < height; ++y) {
5670     I422ToRGB565Row(src_y, src_u, src_v, dst_rgb565, yuvconstants, width);
5671     dst_rgb565 += dst_stride_rgb565;
5672     src_y += src_stride_y;
5673     if (y & 1) {
5674       src_u += src_stride_u;
5675       src_v += src_stride_v;
5676     }
5677   }
5678   return 0;
5679 }
5680 
5681 // Convert I420 to RGB565.
5682 LIBYUV_API
I420ToRGB565(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgb565,int dst_stride_rgb565,int width,int height)5683 int I420ToRGB565(const uint8_t* src_y,
5684                  int src_stride_y,
5685                  const uint8_t* src_u,
5686                  int src_stride_u,
5687                  const uint8_t* src_v,
5688                  int src_stride_v,
5689                  uint8_t* dst_rgb565,
5690                  int dst_stride_rgb565,
5691                  int width,
5692                  int height) {
5693   return I420ToRGB565Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5694                             src_stride_v, dst_rgb565, dst_stride_rgb565,
5695                             &kYuvI601Constants, width, height);
5696 }
5697 
5698 // Convert J420 to RGB565.
5699 LIBYUV_API
J420ToRGB565(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgb565,int dst_stride_rgb565,int width,int height)5700 int J420ToRGB565(const uint8_t* src_y,
5701                  int src_stride_y,
5702                  const uint8_t* src_u,
5703                  int src_stride_u,
5704                  const uint8_t* src_v,
5705                  int src_stride_v,
5706                  uint8_t* dst_rgb565,
5707                  int dst_stride_rgb565,
5708                  int width,
5709                  int height) {
5710   return I420ToRGB565Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5711                             src_stride_v, dst_rgb565, dst_stride_rgb565,
5712                             &kYuvJPEGConstants, width, height);
5713 }
5714 
5715 // Convert H420 to RGB565.
5716 LIBYUV_API
H420ToRGB565(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgb565,int dst_stride_rgb565,int width,int height)5717 int H420ToRGB565(const uint8_t* src_y,
5718                  int src_stride_y,
5719                  const uint8_t* src_u,
5720                  int src_stride_u,
5721                  const uint8_t* src_v,
5722                  int src_stride_v,
5723                  uint8_t* dst_rgb565,
5724                  int dst_stride_rgb565,
5725                  int width,
5726                  int height) {
5727   return I420ToRGB565Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5728                             src_stride_v, dst_rgb565, dst_stride_rgb565,
5729                             &kYuvH709Constants, width, height);
5730 }
5731 
5732 // Convert I422 to RGB565 with specified color matrix.
5733 LIBYUV_API
I422ToRGB565Matrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgb565,int dst_stride_rgb565,const struct YuvConstants * yuvconstants,int width,int height)5734 int I422ToRGB565Matrix(const uint8_t* src_y,
5735                        int src_stride_y,
5736                        const uint8_t* src_u,
5737                        int src_stride_u,
5738                        const uint8_t* src_v,
5739                        int src_stride_v,
5740                        uint8_t* dst_rgb565,
5741                        int dst_stride_rgb565,
5742                        const struct YuvConstants* yuvconstants,
5743                        int width,
5744                        int height) {
5745   int y;
5746   void (*I422ToRGB565Row)(const uint8_t* y_buf, const uint8_t* u_buf,
5747                           const uint8_t* v_buf, uint8_t* rgb_buf,
5748                           const struct YuvConstants* yuvconstants, int width) =
5749       I422ToRGB565Row_C;
5750   assert(yuvconstants);
5751   if (!src_y || !src_u || !src_v || !dst_rgb565 || width <= 0 || height == 0) {
5752     return -1;
5753   }
5754   // Negative height means invert the image.
5755   if (height < 0) {
5756     height = -height;
5757     dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
5758     dst_stride_rgb565 = -dst_stride_rgb565;
5759   }
5760 #if defined(HAS_I422TORGB565ROW_SSSE3)
5761   if (TestCpuFlag(kCpuHasSSSE3)) {
5762     I422ToRGB565Row = I422ToRGB565Row_Any_SSSE3;
5763     if (IS_ALIGNED(width, 8)) {
5764       I422ToRGB565Row = I422ToRGB565Row_SSSE3;
5765     }
5766   }
5767 #endif
5768 #if defined(HAS_I422TORGB565ROW_AVX2)
5769   if (TestCpuFlag(kCpuHasAVX2)) {
5770     I422ToRGB565Row = I422ToRGB565Row_Any_AVX2;
5771     if (IS_ALIGNED(width, 16)) {
5772       I422ToRGB565Row = I422ToRGB565Row_AVX2;
5773     }
5774   }
5775 #endif
5776 #if defined(HAS_I422TORGB565ROW_NEON)
5777   if (TestCpuFlag(kCpuHasNEON)) {
5778     I422ToRGB565Row = I422ToRGB565Row_Any_NEON;
5779     if (IS_ALIGNED(width, 8)) {
5780       I422ToRGB565Row = I422ToRGB565Row_NEON;
5781     }
5782   }
5783 #endif
5784 #if defined(HAS_I422TORGB565ROW_MSA)
5785   if (TestCpuFlag(kCpuHasMSA)) {
5786     I422ToRGB565Row = I422ToRGB565Row_Any_MSA;
5787     if (IS_ALIGNED(width, 8)) {
5788       I422ToRGB565Row = I422ToRGB565Row_MSA;
5789     }
5790   }
5791 #endif
5792 #if defined(HAS_I422TORGB565ROW_LSX)
5793   if (TestCpuFlag(kCpuHasLSX)) {
5794     I422ToRGB565Row = I422ToRGB565Row_Any_LSX;
5795     if (IS_ALIGNED(width, 16)) {
5796       I422ToRGB565Row = I422ToRGB565Row_LSX;
5797     }
5798   }
5799 #endif
5800 #if defined(HAS_I422TORGB565ROW_LASX)
5801   if (TestCpuFlag(kCpuHasLASX)) {
5802     I422ToRGB565Row = I422ToRGB565Row_Any_LASX;
5803     if (IS_ALIGNED(width, 32)) {
5804       I422ToRGB565Row = I422ToRGB565Row_LASX;
5805     }
5806   }
5807 #endif
5808 
5809   for (y = 0; y < height; ++y) {
5810     I422ToRGB565Row(src_y, src_u, src_v, dst_rgb565, yuvconstants, width);
5811     dst_rgb565 += dst_stride_rgb565;
5812     src_y += src_stride_y;
5813     src_u += src_stride_u;
5814     src_v += src_stride_v;
5815   }
5816   return 0;
5817 }
5818 
5819 // Convert I422 to RGB565.
5820 LIBYUV_API
I422ToRGB565(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgb565,int dst_stride_rgb565,int width,int height)5821 int I422ToRGB565(const uint8_t* src_y,
5822                  int src_stride_y,
5823                  const uint8_t* src_u,
5824                  int src_stride_u,
5825                  const uint8_t* src_v,
5826                  int src_stride_v,
5827                  uint8_t* dst_rgb565,
5828                  int dst_stride_rgb565,
5829                  int width,
5830                  int height) {
5831   return I422ToRGB565Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
5832                             src_stride_v, dst_rgb565, dst_stride_rgb565,
5833                             &kYuvI601Constants, width, height);
5834 }
5835 
5836 // Ordered 8x8 dither for 888 to 565.  Values from 0 to 7.
5837 static const uint8_t kDither565_4x4[16] = {
5838     0, 4, 1, 5, 6, 2, 7, 3, 1, 5, 0, 4, 7, 3, 6, 2,
5839 };
5840 
5841 // Convert I420 to RGB565 with dithering.
5842 LIBYUV_API
I420ToRGB565Dither(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgb565,int dst_stride_rgb565,const uint8_t * dither4x4,int width,int height)5843 int I420ToRGB565Dither(const uint8_t* src_y,
5844                        int src_stride_y,
5845                        const uint8_t* src_u,
5846                        int src_stride_u,
5847                        const uint8_t* src_v,
5848                        int src_stride_v,
5849                        uint8_t* dst_rgb565,
5850                        int dst_stride_rgb565,
5851                        const uint8_t* dither4x4,
5852                        int width,
5853                        int height) {
5854   int y;
5855   void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
5856                         const uint8_t* v_buf, uint8_t* rgb_buf,
5857                         const struct YuvConstants* yuvconstants, int width) =
5858       I422ToARGBRow_C;
5859   void (*ARGBToRGB565DitherRow)(const uint8_t* src_argb, uint8_t* dst_rgb,
5860                                 uint32_t dither4, int width) =
5861       ARGBToRGB565DitherRow_C;
5862   if (!src_y || !src_u || !src_v || !dst_rgb565 || width <= 0 || height == 0) {
5863     return -1;
5864   }
5865   // Negative height means invert the image.
5866   if (height < 0) {
5867     height = -height;
5868     dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
5869     dst_stride_rgb565 = -dst_stride_rgb565;
5870   }
5871   if (!dither4x4) {
5872     dither4x4 = kDither565_4x4;
5873   }
5874 #if defined(HAS_I422TOARGBROW_SSSE3)
5875   if (TestCpuFlag(kCpuHasSSSE3)) {
5876     I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
5877     if (IS_ALIGNED(width, 8)) {
5878       I422ToARGBRow = I422ToARGBRow_SSSE3;
5879     }
5880   }
5881 #endif
5882 #if defined(HAS_I422TOARGBROW_AVX2)
5883   if (TestCpuFlag(kCpuHasAVX2)) {
5884     I422ToARGBRow = I422ToARGBRow_Any_AVX2;
5885     if (IS_ALIGNED(width, 16)) {
5886       I422ToARGBRow = I422ToARGBRow_AVX2;
5887     }
5888   }
5889 #endif
5890 #if defined(HAS_I422TOARGBROW_AVX512BW)
5891   if (TestCpuFlag(kCpuHasAVX512BW | kCpuHasAVX512VL) ==
5892       (kCpuHasAVX512BW | kCpuHasAVX512VL)) {
5893     I422ToARGBRow = I422ToARGBRow_Any_AVX512BW;
5894     if (IS_ALIGNED(width, 32)) {
5895       I422ToARGBRow = I422ToARGBRow_AVX512BW;
5896     }
5897   }
5898 #endif
5899 #if defined(HAS_I422TOARGBROW_NEON)
5900   if (TestCpuFlag(kCpuHasNEON)) {
5901     I422ToARGBRow = I422ToARGBRow_Any_NEON;
5902     if (IS_ALIGNED(width, 8)) {
5903       I422ToARGBRow = I422ToARGBRow_NEON;
5904     }
5905   }
5906 #endif
5907 #if defined(HAS_I422TOARGBROW_MSA)
5908   if (TestCpuFlag(kCpuHasMSA)) {
5909     I422ToARGBRow = I422ToARGBRow_Any_MSA;
5910     if (IS_ALIGNED(width, 8)) {
5911       I422ToARGBRow = I422ToARGBRow_MSA;
5912     }
5913   }
5914 #endif
5915 #if defined(HAS_I422TOARGBROW_LSX)
5916   if (TestCpuFlag(kCpuHasLSX)) {
5917     I422ToARGBRow = I422ToARGBRow_Any_LSX;
5918     if (IS_ALIGNED(width, 16)) {
5919       I422ToARGBRow = I422ToARGBRow_LSX;
5920     }
5921   }
5922 #endif
5923 #if defined(HAS_I422TOARGBROW_LASX)
5924   if (TestCpuFlag(kCpuHasLASX)) {
5925     I422ToARGBRow = I422ToARGBRow_Any_LASX;
5926     if (IS_ALIGNED(width, 32)) {
5927       I422ToARGBRow = I422ToARGBRow_LASX;
5928     }
5929   }
5930 #endif
5931 #if defined(HAS_I422TOARGBROW_RVV)
5932   if (TestCpuFlag(kCpuHasRVV)) {
5933     I422ToARGBRow = I422ToARGBRow_RVV;
5934   }
5935 #endif
5936 #if defined(HAS_ARGBTORGB565DITHERROW_SSE2)
5937   if (TestCpuFlag(kCpuHasSSE2)) {
5938     ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_SSE2;
5939     if (IS_ALIGNED(width, 4)) {
5940       ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_SSE2;
5941     }
5942   }
5943 #endif
5944 #if defined(HAS_ARGBTORGB565DITHERROW_AVX2)
5945   if (TestCpuFlag(kCpuHasAVX2)) {
5946     ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_AVX2;
5947     if (IS_ALIGNED(width, 8)) {
5948       ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_AVX2;
5949     }
5950   }
5951 #endif
5952 #if defined(HAS_ARGBTORGB565DITHERROW_NEON)
5953   if (TestCpuFlag(kCpuHasNEON)) {
5954     ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_NEON;
5955     if (IS_ALIGNED(width, 8)) {
5956       ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_NEON;
5957     }
5958   }
5959 #endif
5960 #if defined(HAS_ARGBTORGB565DITHERROW_MSA)
5961   if (TestCpuFlag(kCpuHasMSA)) {
5962     ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_MSA;
5963     if (IS_ALIGNED(width, 8)) {
5964       ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_MSA;
5965     }
5966   }
5967 #endif
5968 #if defined(HAS_ARGBTORGB565DITHERROW_LSX)
5969   if (TestCpuFlag(kCpuHasLSX)) {
5970     ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_LSX;
5971     if (IS_ALIGNED(width, 8)) {
5972       ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_LSX;
5973     }
5974   }
5975 #endif
5976 #if defined(HAS_ARGBTORGB565DITHERROW_LASX)
5977   if (TestCpuFlag(kCpuHasLASX)) {
5978     ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_LASX;
5979     if (IS_ALIGNED(width, 16)) {
5980       ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_LASX;
5981     }
5982   }
5983 #endif
5984   {
5985     // Allocate a row of argb.
5986     align_buffer_64(row_argb, width * 4);
5987     if (!row_argb)
5988       return 1;
5989     for (y = 0; y < height; ++y) {
5990       I422ToARGBRow(src_y, src_u, src_v, row_argb, &kYuvI601Constants, width);
5991       ARGBToRGB565DitherRow(row_argb, dst_rgb565,
5992                             *(const uint32_t*)(dither4x4 + ((y & 3) << 2)),
5993                             width);
5994       dst_rgb565 += dst_stride_rgb565;
5995       src_y += src_stride_y;
5996       if (y & 1) {
5997         src_u += src_stride_u;
5998         src_v += src_stride_v;
5999       }
6000     }
6001     free_aligned_buffer_64(row_argb);
6002   }
6003   return 0;
6004 }
6005 
6006 // Convert I420 to AR30 with matrix.
6007 LIBYUV_API
I420ToAR30Matrix(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height)6008 int I420ToAR30Matrix(const uint8_t* src_y,
6009                      int src_stride_y,
6010                      const uint8_t* src_u,
6011                      int src_stride_u,
6012                      const uint8_t* src_v,
6013                      int src_stride_v,
6014                      uint8_t* dst_ar30,
6015                      int dst_stride_ar30,
6016                      const struct YuvConstants* yuvconstants,
6017                      int width,
6018                      int height) {
6019   int y;
6020   void (*I422ToAR30Row)(const uint8_t* y_buf, const uint8_t* u_buf,
6021                         const uint8_t* v_buf, uint8_t* rgb_buf,
6022                         const struct YuvConstants* yuvconstants, int width) =
6023       I422ToAR30Row_C;
6024 
6025   assert(yuvconstants);
6026   if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
6027     return -1;
6028   }
6029   // Negative height means invert the image.
6030   if (height < 0) {
6031     height = -height;
6032     dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
6033     dst_stride_ar30 = -dst_stride_ar30;
6034   }
6035 
6036 #if defined(HAS_I422TOAR30ROW_SSSE3)
6037   if (TestCpuFlag(kCpuHasSSSE3)) {
6038     I422ToAR30Row = I422ToAR30Row_Any_SSSE3;
6039     if (IS_ALIGNED(width, 8)) {
6040       I422ToAR30Row = I422ToAR30Row_SSSE3;
6041     }
6042   }
6043 #endif
6044 #if defined(HAS_I422TOAR30ROW_AVX2)
6045   if (TestCpuFlag(kCpuHasAVX2)) {
6046     I422ToAR30Row = I422ToAR30Row_Any_AVX2;
6047     if (IS_ALIGNED(width, 16)) {
6048       I422ToAR30Row = I422ToAR30Row_AVX2;
6049     }
6050   }
6051 #endif
6052 
6053   for (y = 0; y < height; ++y) {
6054     I422ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
6055     dst_ar30 += dst_stride_ar30;
6056     src_y += src_stride_y;
6057     if (y & 1) {
6058       src_u += src_stride_u;
6059       src_v += src_stride_v;
6060     }
6061   }
6062   return 0;
6063 }
6064 
6065 // Convert I420 to AR30.
6066 LIBYUV_API
I420ToAR30(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,int width,int height)6067 int I420ToAR30(const uint8_t* src_y,
6068                int src_stride_y,
6069                const uint8_t* src_u,
6070                int src_stride_u,
6071                const uint8_t* src_v,
6072                int src_stride_v,
6073                uint8_t* dst_ar30,
6074                int dst_stride_ar30,
6075                int width,
6076                int height) {
6077   return I420ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
6078                           src_stride_v, dst_ar30, dst_stride_ar30,
6079                           &kYuvI601Constants, width, height);
6080 }
6081 
6082 // Convert H420 to AR30.
6083 LIBYUV_API
H420ToAR30(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,int width,int height)6084 int H420ToAR30(const uint8_t* src_y,
6085                int src_stride_y,
6086                const uint8_t* src_u,
6087                int src_stride_u,
6088                const uint8_t* src_v,
6089                int src_stride_v,
6090                uint8_t* dst_ar30,
6091                int dst_stride_ar30,
6092                int width,
6093                int height) {
6094   return I420ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
6095                           src_stride_v, dst_ar30, dst_stride_ar30,
6096                           &kYvuH709Constants, width, height);
6097 }
6098 
6099 // Convert I420 to AB30.
6100 LIBYUV_API
I420ToAB30(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)6101 int I420ToAB30(const uint8_t* src_y,
6102                int src_stride_y,
6103                const uint8_t* src_u,
6104                int src_stride_u,
6105                const uint8_t* src_v,
6106                int src_stride_v,
6107                uint8_t* dst_ab30,
6108                int dst_stride_ab30,
6109                int width,
6110                int height) {
6111   return I420ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
6112                           src_stride_u, dst_ab30, dst_stride_ab30,
6113                           &kYvuI601Constants, width, height);
6114 }
6115 
6116 // Convert H420 to AB30.
6117 LIBYUV_API
H420ToAB30(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)6118 int H420ToAB30(const uint8_t* src_y,
6119                int src_stride_y,
6120                const uint8_t* src_u,
6121                int src_stride_u,
6122                const uint8_t* src_v,
6123                int src_stride_v,
6124                uint8_t* dst_ab30,
6125                int dst_stride_ab30,
6126                int width,
6127                int height) {
6128   return I420ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
6129                           src_stride_u, dst_ab30, dst_stride_ab30,
6130                           &kYvuH709Constants, width, height);
6131 }
6132 
I420ToARGBMatrixBilinear(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)6133 static int I420ToARGBMatrixBilinear(const uint8_t* src_y,
6134                                     int src_stride_y,
6135                                     const uint8_t* src_u,
6136                                     int src_stride_u,
6137                                     const uint8_t* src_v,
6138                                     int src_stride_v,
6139                                     uint8_t* dst_argb,
6140                                     int dst_stride_argb,
6141                                     const struct YuvConstants* yuvconstants,
6142                                     int width,
6143                                     int height) {
6144   int y;
6145   void (*I444ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
6146                         const uint8_t* v_buf, uint8_t* rgb_buf,
6147                         const struct YuvConstants* yuvconstants, int width) =
6148       I444ToARGBRow_C;
6149   void (*Scale2RowUp_Bilinear)(const uint8_t* src_ptr, ptrdiff_t src_stride,
6150                                uint8_t* dst_ptr, ptrdiff_t dst_stride,
6151                                int dst_width) = ScaleRowUp2_Bilinear_Any_C;
6152   void (*ScaleRowUp2_Linear)(const uint8_t* src_ptr, uint8_t* dst_ptr,
6153                              int dst_width) = ScaleRowUp2_Linear_Any_C;
6154   assert(yuvconstants);
6155   if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
6156     return -1;
6157   }
6158   // Negative height means invert the image.
6159   if (height < 0) {
6160     height = -height;
6161     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
6162     dst_stride_argb = -dst_stride_argb;
6163   }
6164 #if defined(HAS_I444TOARGBROW_SSSE3)
6165   if (TestCpuFlag(kCpuHasSSSE3)) {
6166     I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
6167     if (IS_ALIGNED(width, 8)) {
6168       I444ToARGBRow = I444ToARGBRow_SSSE3;
6169     }
6170   }
6171 #endif
6172 #if defined(HAS_I444TOARGBROW_AVX2)
6173   if (TestCpuFlag(kCpuHasAVX2)) {
6174     I444ToARGBRow = I444ToARGBRow_Any_AVX2;
6175     if (IS_ALIGNED(width, 16)) {
6176       I444ToARGBRow = I444ToARGBRow_AVX2;
6177     }
6178   }
6179 #endif
6180 #if defined(HAS_I444TOARGBROW_NEON)
6181   if (TestCpuFlag(kCpuHasNEON)) {
6182     I444ToARGBRow = I444ToARGBRow_Any_NEON;
6183     if (IS_ALIGNED(width, 8)) {
6184       I444ToARGBRow = I444ToARGBRow_NEON;
6185     }
6186   }
6187 #endif
6188 #if defined(HAS_I444TOARGBROW_MSA)
6189   if (TestCpuFlag(kCpuHasMSA)) {
6190     I444ToARGBRow = I444ToARGBRow_Any_MSA;
6191     if (IS_ALIGNED(width, 8)) {
6192       I444ToARGBRow = I444ToARGBRow_MSA;
6193     }
6194   }
6195 #endif
6196 #if defined(HAS_I444TOARGBROW_LASX)
6197   if (TestCpuFlag(kCpuHasLASX)) {
6198     I444ToARGBRow = I444ToARGBRow_Any_LASX;
6199     if (IS_ALIGNED(width, 32)) {
6200       I444ToARGBRow = I444ToARGBRow_LASX;
6201     }
6202   }
6203 #endif
6204 #if defined(HAS_I444TOARGBROW_RVV)
6205   if (TestCpuFlag(kCpuHasRVV)) {
6206     I444ToARGBRow = I444ToARGBRow_RVV;
6207   }
6208 #endif
6209 
6210 #if defined(HAS_SCALEROWUP2_BILINEAR_SSE2)
6211   if (TestCpuFlag(kCpuHasSSE2)) {
6212     Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_SSE2;
6213     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSE2;
6214   }
6215 #endif
6216 
6217 #if defined(HAS_SCALEROWUP2_BILINEAR_SSSE3)
6218   if (TestCpuFlag(kCpuHasSSSE3)) {
6219     Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_SSSE3;
6220     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSSE3;
6221   }
6222 #endif
6223 
6224 #if defined(HAS_SCALEROWUP2_BILINEAR_AVX2)
6225   if (TestCpuFlag(kCpuHasAVX2)) {
6226     Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_AVX2;
6227     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_AVX2;
6228   }
6229 #endif
6230 
6231 #if defined(HAS_SCALEROWUP2_BILINEAR_NEON)
6232   if (TestCpuFlag(kCpuHasNEON)) {
6233     Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_NEON;
6234     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_NEON;
6235   }
6236 #endif
6237 #if defined(HAS_SCALEROWUP2_BILINEAR_RVV)
6238   if (TestCpuFlag(kCpuHasRVV)) {
6239     Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_RVV;
6240     ScaleRowUp2_Linear = ScaleRowUp2_Linear_RVV;
6241   }
6242 #endif
6243 
6244   // alloc 4 lines temp
6245   const int row_size = (width + 31) & ~31;
6246   align_buffer_64(row, row_size * 4);
6247   uint8_t* temp_u_1 = row;
6248   uint8_t* temp_u_2 = row + row_size;
6249   uint8_t* temp_v_1 = row + row_size * 2;
6250   uint8_t* temp_v_2 = row + row_size * 3;
6251   if (!row)
6252     return 1;
6253 
6254   ScaleRowUp2_Linear(src_u, temp_u_1, width);
6255   ScaleRowUp2_Linear(src_v, temp_v_1, width);
6256   I444ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
6257   dst_argb += dst_stride_argb;
6258   src_y += src_stride_y;
6259 
6260   for (y = 0; y < height - 2; y += 2) {
6261     Scale2RowUp_Bilinear(src_u, src_stride_u, temp_u_1, row_size, width);
6262     Scale2RowUp_Bilinear(src_v, src_stride_v, temp_v_1, row_size, width);
6263     I444ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
6264     dst_argb += dst_stride_argb;
6265     src_y += src_stride_y;
6266     I444ToARGBRow(src_y, temp_u_2, temp_v_2, dst_argb, yuvconstants, width);
6267     dst_argb += dst_stride_argb;
6268     src_y += src_stride_y;
6269     src_u += src_stride_u;
6270     src_v += src_stride_v;
6271   }
6272 
6273   if (!(height & 1)) {
6274     ScaleRowUp2_Linear(src_u, temp_u_1, width);
6275     ScaleRowUp2_Linear(src_v, temp_v_1, width);
6276     I444ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
6277   }
6278 
6279   free_aligned_buffer_64(row);
6280   return 0;
6281 }
6282 
I422ToARGBMatrixLinear(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)6283 static int I422ToARGBMatrixLinear(const uint8_t* src_y,
6284                                   int src_stride_y,
6285                                   const uint8_t* src_u,
6286                                   int src_stride_u,
6287                                   const uint8_t* src_v,
6288                                   int src_stride_v,
6289                                   uint8_t* dst_argb,
6290                                   int dst_stride_argb,
6291                                   const struct YuvConstants* yuvconstants,
6292                                   int width,
6293                                   int height) {
6294   int y;
6295   void (*I444ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
6296                         const uint8_t* v_buf, uint8_t* rgb_buf,
6297                         const struct YuvConstants* yuvconstants, int width) =
6298       I444ToARGBRow_C;
6299   void (*ScaleRowUp2_Linear)(const uint8_t* src_ptr, uint8_t* dst_ptr,
6300                              int dst_width) = ScaleRowUp2_Linear_Any_C;
6301   assert(yuvconstants);
6302   if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
6303     return -1;
6304   }
6305   // Negative height means invert the image.
6306   if (height < 0) {
6307     height = -height;
6308     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
6309     dst_stride_argb = -dst_stride_argb;
6310   }
6311 #if defined(HAS_I444TOARGBROW_SSSE3)
6312   if (TestCpuFlag(kCpuHasSSSE3)) {
6313     I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
6314     if (IS_ALIGNED(width, 8)) {
6315       I444ToARGBRow = I444ToARGBRow_SSSE3;
6316     }
6317   }
6318 #endif
6319 #if defined(HAS_I444TOARGBROW_AVX2)
6320   if (TestCpuFlag(kCpuHasAVX2)) {
6321     I444ToARGBRow = I444ToARGBRow_Any_AVX2;
6322     if (IS_ALIGNED(width, 16)) {
6323       I444ToARGBRow = I444ToARGBRow_AVX2;
6324     }
6325   }
6326 #endif
6327 #if defined(HAS_I444TOARGBROW_NEON)
6328   if (TestCpuFlag(kCpuHasNEON)) {
6329     I444ToARGBRow = I444ToARGBRow_Any_NEON;
6330     if (IS_ALIGNED(width, 8)) {
6331       I444ToARGBRow = I444ToARGBRow_NEON;
6332     }
6333   }
6334 #endif
6335 #if defined(HAS_I444TOARGBROW_MSA)
6336   if (TestCpuFlag(kCpuHasMSA)) {
6337     I444ToARGBRow = I444ToARGBRow_Any_MSA;
6338     if (IS_ALIGNED(width, 8)) {
6339       I444ToARGBRow = I444ToARGBRow_MSA;
6340     }
6341   }
6342 #endif
6343 #if defined(HAS_I444TOARGBROW_LASX)
6344   if (TestCpuFlag(kCpuHasLASX)) {
6345     I444ToARGBRow = I444ToARGBRow_Any_LASX;
6346     if (IS_ALIGNED(width, 32)) {
6347       I444ToARGBRow = I444ToARGBRow_LASX;
6348     }
6349   }
6350 #endif
6351 #if defined(HAS_I444TOARGBROW_RVV)
6352   if (TestCpuFlag(kCpuHasRVV)) {
6353     I444ToARGBRow = I444ToARGBRow_RVV;
6354   }
6355 #endif
6356 #if defined(HAS_SCALEROWUP2_LINEAR_SSE2)
6357   if (TestCpuFlag(kCpuHasSSE2)) {
6358     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSE2;
6359   }
6360 #endif
6361 #if defined(HAS_SCALEROWUP2_LINEAR_SSSE3)
6362   if (TestCpuFlag(kCpuHasSSSE3)) {
6363     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSSE3;
6364   }
6365 #endif
6366 #if defined(HAS_SCALEROWUP2_LINEAR_AVX2)
6367   if (TestCpuFlag(kCpuHasAVX2)) {
6368     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_AVX2;
6369   }
6370 #endif
6371 #if defined(HAS_SCALEROWUP2_LINEAR_NEON)
6372   if (TestCpuFlag(kCpuHasNEON)) {
6373     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_NEON;
6374   }
6375 #endif
6376 #if defined(HAS_SCALEROWUP2_LINEAR_RVV)
6377   if (TestCpuFlag(kCpuHasRVV)) {
6378     ScaleRowUp2_Linear = ScaleRowUp2_Linear_RVV;
6379   }
6380 #endif
6381 
6382   // alloc 2 lines temp
6383   const int row_size = (width + 31) & ~31;
6384   align_buffer_64(row, row_size * 2);
6385   uint8_t* temp_u = row;
6386   uint8_t* temp_v = row + row_size;
6387   if (!row)
6388     return 1;
6389 
6390   for (y = 0; y < height; ++y) {
6391     ScaleRowUp2_Linear(src_u, temp_u, width);
6392     ScaleRowUp2_Linear(src_v, temp_v, width);
6393     I444ToARGBRow(src_y, temp_u, temp_v, dst_argb, yuvconstants, width);
6394     dst_argb += dst_stride_argb;
6395     src_y += src_stride_y;
6396     src_u += src_stride_u;
6397     src_v += src_stride_v;
6398   }
6399 
6400   free_aligned_buffer_64(row);
6401   return 0;
6402 }
6403 
I420ToRGB24MatrixBilinear(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgb24,int dst_stride_rgb24,const struct YuvConstants * yuvconstants,int width,int height)6404 static int I420ToRGB24MatrixBilinear(const uint8_t* src_y,
6405                                      int src_stride_y,
6406                                      const uint8_t* src_u,
6407                                      int src_stride_u,
6408                                      const uint8_t* src_v,
6409                                      int src_stride_v,
6410                                      uint8_t* dst_rgb24,
6411                                      int dst_stride_rgb24,
6412                                      const struct YuvConstants* yuvconstants,
6413                                      int width,
6414                                      int height) {
6415   int y;
6416   void (*I444ToRGB24Row)(const uint8_t* y_buf, const uint8_t* u_buf,
6417                          const uint8_t* v_buf, uint8_t* rgb_buf,
6418                          const struct YuvConstants* yuvconstants, int width) =
6419       I444ToRGB24Row_C;
6420   void (*Scale2RowUp_Bilinear)(const uint8_t* src_ptr, ptrdiff_t src_stride,
6421                                uint8_t* dst_ptr, ptrdiff_t dst_stride,
6422                                int dst_width) = ScaleRowUp2_Bilinear_Any_C;
6423   void (*ScaleRowUp2_Linear)(const uint8_t* src_ptr, uint8_t* dst_ptr,
6424                              int dst_width) = ScaleRowUp2_Linear_Any_C;
6425   assert(yuvconstants);
6426   if (!src_y || !src_u || !src_v || !dst_rgb24 || width <= 0 || height == 0) {
6427     return -1;
6428   }
6429   // Negative height means invert the image.
6430   if (height < 0) {
6431     height = -height;
6432     dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
6433     dst_stride_rgb24 = -dst_stride_rgb24;
6434   }
6435 #if defined(HAS_I444TORGB24ROW_SSSE3)
6436   if (TestCpuFlag(kCpuHasSSSE3)) {
6437     I444ToRGB24Row = I444ToRGB24Row_Any_SSSE3;
6438     if (IS_ALIGNED(width, 16)) {
6439       I444ToRGB24Row = I444ToRGB24Row_SSSE3;
6440     }
6441   }
6442 #endif
6443 #if defined(HAS_I444TORGB24ROW_AVX2)
6444   if (TestCpuFlag(kCpuHasAVX2)) {
6445     I444ToRGB24Row = I444ToRGB24Row_Any_AVX2;
6446     if (IS_ALIGNED(width, 32)) {
6447       I444ToRGB24Row = I444ToRGB24Row_AVX2;
6448     }
6449   }
6450 #endif
6451 #if defined(HAS_I444TORGB24ROW_NEON)
6452   if (TestCpuFlag(kCpuHasNEON)) {
6453     I444ToRGB24Row = I444ToRGB24Row_Any_NEON;
6454     if (IS_ALIGNED(width, 8)) {
6455       I444ToRGB24Row = I444ToRGB24Row_NEON;
6456     }
6457   }
6458 #endif
6459 #if defined(HAS_I444TORGB24ROW_MSA)
6460   if (TestCpuFlag(kCpuHasMSA)) {
6461     I444ToRGB24Row = I444ToRGB24Row_Any_MSA;
6462     if (IS_ALIGNED(width, 8)) {
6463       I444ToRGB24Row = I444ToRGB24Row_MSA;
6464     }
6465   }
6466 #endif
6467 #if defined(HAS_I444TORGB24ROW_LASX)
6468   if (TestCpuFlag(kCpuHasLASX)) {
6469     I444ToRGB24Row = I444ToRGB24Row_Any_LASX;
6470     if (IS_ALIGNED(width, 32)) {
6471       I444ToRGB24Row = I444ToRGB24Row_LASX;
6472     }
6473   }
6474 #endif
6475 #if defined(HAS_I444TORGB24ROW_RVV)
6476   if (TestCpuFlag(kCpuHasRVV)) {
6477     I444ToRGB24Row = I444ToRGB24Row_RVV;
6478   }
6479 #endif
6480 
6481 #if defined(HAS_SCALEROWUP2_BILINEAR_SSE2)
6482   if (TestCpuFlag(kCpuHasSSE2)) {
6483     Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_SSE2;
6484     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSE2;
6485   }
6486 #endif
6487 
6488 #if defined(HAS_SCALEROWUP2_BILINEAR_SSSE3)
6489   if (TestCpuFlag(kCpuHasSSSE3)) {
6490     Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_SSSE3;
6491     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSSE3;
6492   }
6493 #endif
6494 
6495 #if defined(HAS_SCALEROWUP2_BILINEAR_AVX2)
6496   if (TestCpuFlag(kCpuHasAVX2)) {
6497     Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_AVX2;
6498     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_AVX2;
6499   }
6500 #endif
6501 
6502 #if defined(HAS_SCALEROWUP2_BILINEAR_NEON)
6503   if (TestCpuFlag(kCpuHasNEON)) {
6504     Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_NEON;
6505     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_NEON;
6506   }
6507 #endif
6508 #if defined(HAS_SCALEROWUP2_BILINEAR_RVV)
6509   if (TestCpuFlag(kCpuHasRVV)) {
6510     Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_RVV;
6511     ScaleRowUp2_Linear = ScaleRowUp2_Linear_RVV;
6512   }
6513 #endif
6514 
6515   // alloc 4 lines temp
6516   const int row_size = (width + 31) & ~31;
6517   align_buffer_64(row, row_size * 4);
6518   uint8_t* temp_u_1 = row;
6519   uint8_t* temp_u_2 = row + row_size;
6520   uint8_t* temp_v_1 = row + row_size * 2;
6521   uint8_t* temp_v_2 = row + row_size * 3;
6522   if (!row)
6523     return 1;
6524 
6525   ScaleRowUp2_Linear(src_u, temp_u_1, width);
6526   ScaleRowUp2_Linear(src_v, temp_v_1, width);
6527   I444ToRGB24Row(src_y, temp_u_1, temp_v_1, dst_rgb24, yuvconstants, width);
6528   dst_rgb24 += dst_stride_rgb24;
6529   src_y += src_stride_y;
6530 
6531   for (y = 0; y < height - 2; y += 2) {
6532     Scale2RowUp_Bilinear(src_u, src_stride_u, temp_u_1, row_size, width);
6533     Scale2RowUp_Bilinear(src_v, src_stride_v, temp_v_1, row_size, width);
6534     I444ToRGB24Row(src_y, temp_u_1, temp_v_1, dst_rgb24, yuvconstants, width);
6535     dst_rgb24 += dst_stride_rgb24;
6536     src_y += src_stride_y;
6537     I444ToRGB24Row(src_y, temp_u_2, temp_v_2, dst_rgb24, yuvconstants, width);
6538     dst_rgb24 += dst_stride_rgb24;
6539     src_y += src_stride_y;
6540     src_u += src_stride_u;
6541     src_v += src_stride_v;
6542   }
6543 
6544   if (!(height & 1)) {
6545     ScaleRowUp2_Linear(src_u, temp_u_1, width);
6546     ScaleRowUp2_Linear(src_v, temp_v_1, width);
6547     I444ToRGB24Row(src_y, temp_u_1, temp_v_1, dst_rgb24, yuvconstants, width);
6548   }
6549 
6550   free_aligned_buffer_64(row);
6551   return 0;
6552 }
6553 
I010ToAR30MatrixBilinear(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height)6554 static int I010ToAR30MatrixBilinear(const uint16_t* src_y,
6555                                     int src_stride_y,
6556                                     const uint16_t* src_u,
6557                                     int src_stride_u,
6558                                     const uint16_t* src_v,
6559                                     int src_stride_v,
6560                                     uint8_t* dst_ar30,
6561                                     int dst_stride_ar30,
6562                                     const struct YuvConstants* yuvconstants,
6563                                     int width,
6564                                     int height) {
6565   int y;
6566   void (*I410ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
6567                         const uint16_t* v_buf, uint8_t* rgb_buf,
6568                         const struct YuvConstants* yuvconstants, int width) =
6569       I410ToAR30Row_C;
6570   void (*Scale2RowUp_Bilinear_12)(
6571       const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr,
6572       ptrdiff_t dst_stride, int dst_width) = ScaleRowUp2_Bilinear_16_Any_C;
6573   void (*ScaleRowUp2_Linear_12)(const uint16_t* src_ptr, uint16_t* dst_ptr,
6574                                 int dst_width) = ScaleRowUp2_Linear_16_Any_C;
6575   assert(yuvconstants);
6576   if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
6577     return -1;
6578   }
6579   // Negative height means invert the image.
6580   if (height < 0) {
6581     height = -height;
6582     dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
6583     dst_stride_ar30 = -dst_stride_ar30;
6584   }
6585 #if defined(HAS_I410TOAR30ROW_SSSE3)
6586   if (TestCpuFlag(kCpuHasSSSE3)) {
6587     I410ToAR30Row = I410ToAR30Row_Any_SSSE3;
6588     if (IS_ALIGNED(width, 8)) {
6589       I410ToAR30Row = I410ToAR30Row_SSSE3;
6590     }
6591   }
6592 #endif
6593 #if defined(HAS_I410TOAR30ROW_AVX2)
6594   if (TestCpuFlag(kCpuHasAVX2)) {
6595     I410ToAR30Row = I410ToAR30Row_Any_AVX2;
6596     if (IS_ALIGNED(width, 16)) {
6597       I410ToAR30Row = I410ToAR30Row_AVX2;
6598     }
6599   }
6600 #endif
6601 
6602 #if defined(HAS_SCALEROWUP2_BILINEAR_12_SSSE3)
6603   if (TestCpuFlag(kCpuHasSSSE3)) {
6604     Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_SSSE3;
6605     ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_SSSE3;
6606   }
6607 #endif
6608 
6609 #if defined(HAS_SCALEROWUP2_BILINEAR_12_AVX2)
6610   if (TestCpuFlag(kCpuHasAVX2)) {
6611     Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_AVX2;
6612     ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_AVX2;
6613   }
6614 #endif
6615 
6616 #if defined(HAS_SCALEROWUP2_BILINEAR_12_NEON)
6617   if (TestCpuFlag(kCpuHasNEON)) {
6618     Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_NEON;
6619     ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_NEON;
6620   }
6621 #endif
6622 
6623   // alloc 4 lines temp
6624   const int row_size = (width + 31) & ~31;
6625   align_buffer_64(row, row_size * 4 * sizeof(uint16_t));
6626   uint16_t* temp_u_1 = (uint16_t*)(row);
6627   uint16_t* temp_u_2 = (uint16_t*)(row) + row_size;
6628   uint16_t* temp_v_1 = (uint16_t*)(row) + row_size * 2;
6629   uint16_t* temp_v_2 = (uint16_t*)(row) + row_size * 3;
6630   if (!row)
6631     return 1;
6632 
6633   ScaleRowUp2_Linear_12(src_u, temp_u_1, width);
6634   ScaleRowUp2_Linear_12(src_v, temp_v_1, width);
6635   I410ToAR30Row(src_y, temp_u_1, temp_v_1, dst_ar30, yuvconstants, width);
6636   dst_ar30 += dst_stride_ar30;
6637   src_y += src_stride_y;
6638 
6639   for (y = 0; y < height - 2; y += 2) {
6640     Scale2RowUp_Bilinear_12(src_u, src_stride_u, temp_u_1, row_size, width);
6641     Scale2RowUp_Bilinear_12(src_v, src_stride_v, temp_v_1, row_size, width);
6642     I410ToAR30Row(src_y, temp_u_1, temp_v_1, dst_ar30, yuvconstants, width);
6643     dst_ar30 += dst_stride_ar30;
6644     src_y += src_stride_y;
6645     I410ToAR30Row(src_y, temp_u_2, temp_v_2, dst_ar30, yuvconstants, width);
6646     dst_ar30 += dst_stride_ar30;
6647     src_y += src_stride_y;
6648     src_u += src_stride_u;
6649     src_v += src_stride_v;
6650   }
6651 
6652   if (!(height & 1)) {
6653     ScaleRowUp2_Linear_12(src_u, temp_u_1, width);
6654     ScaleRowUp2_Linear_12(src_v, temp_v_1, width);
6655     I410ToAR30Row(src_y, temp_u_1, temp_v_1, dst_ar30, yuvconstants, width);
6656   }
6657 
6658   free_aligned_buffer_64(row);
6659 
6660   return 0;
6661 }
6662 
I210ToAR30MatrixLinear(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height)6663 static int I210ToAR30MatrixLinear(const uint16_t* src_y,
6664                                   int src_stride_y,
6665                                   const uint16_t* src_u,
6666                                   int src_stride_u,
6667                                   const uint16_t* src_v,
6668                                   int src_stride_v,
6669                                   uint8_t* dst_ar30,
6670                                   int dst_stride_ar30,
6671                                   const struct YuvConstants* yuvconstants,
6672                                   int width,
6673                                   int height) {
6674   int y;
6675   void (*I410ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
6676                         const uint16_t* v_buf, uint8_t* rgb_buf,
6677                         const struct YuvConstants* yuvconstants, int width) =
6678       I410ToAR30Row_C;
6679   void (*ScaleRowUp2_Linear_12)(const uint16_t* src_ptr, uint16_t* dst_ptr,
6680                                 int dst_width) = ScaleRowUp2_Linear_16_Any_C;
6681   assert(yuvconstants);
6682   if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
6683     return -1;
6684   }
6685   // Negative height means invert the image.
6686   if (height < 0) {
6687     height = -height;
6688     dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
6689     dst_stride_ar30 = -dst_stride_ar30;
6690   }
6691 #if defined(HAS_I410TOAR30ROW_SSSE3)
6692   if (TestCpuFlag(kCpuHasSSSE3)) {
6693     I410ToAR30Row = I410ToAR30Row_Any_SSSE3;
6694     if (IS_ALIGNED(width, 8)) {
6695       I410ToAR30Row = I410ToAR30Row_SSSE3;
6696     }
6697   }
6698 #endif
6699 #if defined(HAS_I410TOAR30ROW_AVX2)
6700   if (TestCpuFlag(kCpuHasAVX2)) {
6701     I410ToAR30Row = I410ToAR30Row_Any_AVX2;
6702     if (IS_ALIGNED(width, 16)) {
6703       I410ToAR30Row = I410ToAR30Row_AVX2;
6704     }
6705   }
6706 #endif
6707 
6708 #if defined(HAS_SCALEROWUP2_LINEAR_12_SSSE3)
6709   if (TestCpuFlag(kCpuHasSSSE3)) {
6710     ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_SSSE3;
6711   }
6712 #endif
6713 #if defined(HAS_SCALEROWUP2_LINEAR_12_AVX2)
6714   if (TestCpuFlag(kCpuHasAVX2)) {
6715     ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_AVX2;
6716   }
6717 #endif
6718 #if defined(HAS_SCALEROWUP2_LINEAR_12_NEON)
6719   if (TestCpuFlag(kCpuHasNEON)) {
6720     ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_NEON;
6721   }
6722 #endif
6723 
6724   // alloc 2 lines temp
6725   const int row_size = (width + 31) & ~31;
6726   align_buffer_64(row, row_size * 2 * sizeof(uint16_t));
6727   uint16_t* temp_u = (uint16_t*)(row);
6728   uint16_t* temp_v = (uint16_t*)(row) + row_size;
6729   if (!row)
6730     return 1;
6731 
6732   for (y = 0; y < height; ++y) {
6733     ScaleRowUp2_Linear_12(src_u, temp_u, width);
6734     ScaleRowUp2_Linear_12(src_v, temp_v, width);
6735     I410ToAR30Row(src_y, temp_u, temp_v, dst_ar30, yuvconstants, width);
6736     dst_ar30 += dst_stride_ar30;
6737     src_y += src_stride_y;
6738     src_u += src_stride_u;
6739     src_v += src_stride_v;
6740   }
6741   free_aligned_buffer_64(row);
6742   return 0;
6743 }
6744 
I010ToARGBMatrixBilinear(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)6745 static int I010ToARGBMatrixBilinear(const uint16_t* src_y,
6746                                     int src_stride_y,
6747                                     const uint16_t* src_u,
6748                                     int src_stride_u,
6749                                     const uint16_t* src_v,
6750                                     int src_stride_v,
6751                                     uint8_t* dst_argb,
6752                                     int dst_stride_argb,
6753                                     const struct YuvConstants* yuvconstants,
6754                                     int width,
6755                                     int height) {
6756   int y;
6757   void (*I410ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
6758                         const uint16_t* v_buf, uint8_t* rgb_buf,
6759                         const struct YuvConstants* yuvconstants, int width) =
6760       I410ToARGBRow_C;
6761   void (*Scale2RowUp_Bilinear_12)(
6762       const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr,
6763       ptrdiff_t dst_stride, int dst_width) = ScaleRowUp2_Bilinear_16_Any_C;
6764   void (*ScaleRowUp2_Linear_12)(const uint16_t* src_ptr, uint16_t* dst_ptr,
6765                                 int dst_width) = ScaleRowUp2_Linear_16_Any_C;
6766   assert(yuvconstants);
6767   if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
6768     return -1;
6769   }
6770   // Negative height means invert the image.
6771   if (height < 0) {
6772     height = -height;
6773     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
6774     dst_stride_argb = -dst_stride_argb;
6775   }
6776 #if defined(HAS_I410TOARGBROW_SSSE3)
6777   if (TestCpuFlag(kCpuHasSSSE3)) {
6778     I410ToARGBRow = I410ToARGBRow_Any_SSSE3;
6779     if (IS_ALIGNED(width, 8)) {
6780       I410ToARGBRow = I410ToARGBRow_SSSE3;
6781     }
6782   }
6783 #endif
6784 #if defined(HAS_I410TOARGBROW_AVX2)
6785   if (TestCpuFlag(kCpuHasAVX2)) {
6786     I410ToARGBRow = I410ToARGBRow_Any_AVX2;
6787     if (IS_ALIGNED(width, 16)) {
6788       I410ToARGBRow = I410ToARGBRow_AVX2;
6789     }
6790   }
6791 #endif
6792 
6793 #if defined(HAS_SCALEROWUP2_BILINEAR_12_SSSE3)
6794   if (TestCpuFlag(kCpuHasSSSE3)) {
6795     Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_SSSE3;
6796     ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_SSSE3;
6797   }
6798 #endif
6799 
6800 #if defined(HAS_SCALEROWUP2_BILINEAR_12_AVX2)
6801   if (TestCpuFlag(kCpuHasAVX2)) {
6802     Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_AVX2;
6803     ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_AVX2;
6804   }
6805 #endif
6806 
6807 #if defined(HAS_SCALEROWUP2_BILINEAR_12_NEON)
6808   if (TestCpuFlag(kCpuHasNEON)) {
6809     Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_NEON;
6810     ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_NEON;
6811   }
6812 #endif
6813 
6814   // alloc 4 lines temp
6815   const int row_size = (width + 31) & ~31;
6816   align_buffer_64(row, row_size * 4 * sizeof(uint16_t));
6817   uint16_t* temp_u_1 = (uint16_t*)(row);
6818   uint16_t* temp_u_2 = (uint16_t*)(row) + row_size;
6819   uint16_t* temp_v_1 = (uint16_t*)(row) + row_size * 2;
6820   uint16_t* temp_v_2 = (uint16_t*)(row) + row_size * 3;
6821   if (!row)
6822     return 1;
6823 
6824   ScaleRowUp2_Linear_12(src_u, temp_u_1, width);
6825   ScaleRowUp2_Linear_12(src_v, temp_v_1, width);
6826   I410ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
6827   dst_argb += dst_stride_argb;
6828   src_y += src_stride_y;
6829 
6830   for (y = 0; y < height - 2; y += 2) {
6831     Scale2RowUp_Bilinear_12(src_u, src_stride_u, temp_u_1, row_size, width);
6832     Scale2RowUp_Bilinear_12(src_v, src_stride_v, temp_v_1, row_size, width);
6833     I410ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
6834     dst_argb += dst_stride_argb;
6835     src_y += src_stride_y;
6836     I410ToARGBRow(src_y, temp_u_2, temp_v_2, dst_argb, yuvconstants, width);
6837     dst_argb += dst_stride_argb;
6838     src_y += src_stride_y;
6839     src_u += src_stride_u;
6840     src_v += src_stride_v;
6841   }
6842 
6843   if (!(height & 1)) {
6844     ScaleRowUp2_Linear_12(src_u, temp_u_1, width);
6845     ScaleRowUp2_Linear_12(src_v, temp_v_1, width);
6846     I410ToARGBRow(src_y, temp_u_1, temp_v_1, dst_argb, yuvconstants, width);
6847   }
6848 
6849   free_aligned_buffer_64(row);
6850   return 0;
6851 }
6852 
I210ToARGBMatrixLinear(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)6853 static int I210ToARGBMatrixLinear(const uint16_t* src_y,
6854                                   int src_stride_y,
6855                                   const uint16_t* src_u,
6856                                   int src_stride_u,
6857                                   const uint16_t* src_v,
6858                                   int src_stride_v,
6859                                   uint8_t* dst_argb,
6860                                   int dst_stride_argb,
6861                                   const struct YuvConstants* yuvconstants,
6862                                   int width,
6863                                   int height) {
6864   int y;
6865   void (*I410ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
6866                         const uint16_t* v_buf, uint8_t* rgb_buf,
6867                         const struct YuvConstants* yuvconstants, int width) =
6868       I410ToARGBRow_C;
6869   void (*ScaleRowUp2_Linear_12)(const uint16_t* src_ptr, uint16_t* dst_ptr,
6870                                 int dst_width) = ScaleRowUp2_Linear_16_Any_C;
6871   assert(yuvconstants);
6872   if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
6873     return -1;
6874   }
6875   // Negative height means invert the image.
6876   if (height < 0) {
6877     height = -height;
6878     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
6879     dst_stride_argb = -dst_stride_argb;
6880   }
6881 #if defined(HAS_I410TOARGBROW_SSSE3)
6882   if (TestCpuFlag(kCpuHasSSSE3)) {
6883     I410ToARGBRow = I410ToARGBRow_Any_SSSE3;
6884     if (IS_ALIGNED(width, 8)) {
6885       I410ToARGBRow = I410ToARGBRow_SSSE3;
6886     }
6887   }
6888 #endif
6889 #if defined(HAS_I410TOARGBROW_AVX2)
6890   if (TestCpuFlag(kCpuHasAVX2)) {
6891     I410ToARGBRow = I410ToARGBRow_Any_AVX2;
6892     if (IS_ALIGNED(width, 16)) {
6893       I410ToARGBRow = I410ToARGBRow_AVX2;
6894     }
6895   }
6896 #endif
6897 
6898 #if defined(HAS_SCALEROWUP2_LINEAR_12_SSSE3)
6899   if (TestCpuFlag(kCpuHasSSSE3)) {
6900     ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_SSSE3;
6901   }
6902 #endif
6903 #if defined(HAS_SCALEROWUP2_LINEAR_12_AVX2)
6904   if (TestCpuFlag(kCpuHasAVX2)) {
6905     ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_AVX2;
6906   }
6907 #endif
6908 #if defined(HAS_SCALEROWUP2_LINEAR_12_NEON)
6909   if (TestCpuFlag(kCpuHasNEON)) {
6910     ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_NEON;
6911   }
6912 #endif
6913 
6914   // alloc 2 lines temp
6915   const int row_size = (width + 31) & ~31;
6916   align_buffer_64(row, row_size * 2 * sizeof(uint16_t));
6917   uint16_t* temp_u = (uint16_t*)(row);
6918   uint16_t* temp_v = (uint16_t*)(row) + row_size;
6919   if (!row)
6920     return 1;
6921 
6922   for (y = 0; y < height; ++y) {
6923     ScaleRowUp2_Linear_12(src_u, temp_u, width);
6924     ScaleRowUp2_Linear_12(src_v, temp_v, width);
6925     I410ToARGBRow(src_y, temp_u, temp_v, dst_argb, yuvconstants, width);
6926     dst_argb += dst_stride_argb;
6927     src_y += src_stride_y;
6928     src_u += src_stride_u;
6929     src_v += src_stride_v;
6930   }
6931 
6932   free_aligned_buffer_64(row);
6933   return 0;
6934 }
6935 
I420AlphaToARGBMatrixBilinear(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,const uint8_t * src_a,int src_stride_a,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,int attenuate)6936 static int I420AlphaToARGBMatrixBilinear(
6937     const uint8_t* src_y,
6938     int src_stride_y,
6939     const uint8_t* src_u,
6940     int src_stride_u,
6941     const uint8_t* src_v,
6942     int src_stride_v,
6943     const uint8_t* src_a,
6944     int src_stride_a,
6945     uint8_t* dst_argb,
6946     int dst_stride_argb,
6947     const struct YuvConstants* yuvconstants,
6948     int width,
6949     int height,
6950     int attenuate) {
6951   int y;
6952   void (*I444AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
6953                              const uint8_t* v_buf, const uint8_t* a_buf,
6954                              uint8_t* dst_argb,
6955                              const struct YuvConstants* yuvconstants,
6956                              int width) = I444AlphaToARGBRow_C;
6957   void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
6958                            int width) = ARGBAttenuateRow_C;
6959   void (*Scale2RowUp_Bilinear)(const uint8_t* src_ptr, ptrdiff_t src_stride,
6960                                uint8_t* dst_ptr, ptrdiff_t dst_stride,
6961                                int dst_width) = ScaleRowUp2_Bilinear_Any_C;
6962   void (*ScaleRowUp2_Linear)(const uint8_t* src_ptr, uint8_t* dst_ptr,
6963                              int dst_width) = ScaleRowUp2_Linear_Any_C;
6964   assert(yuvconstants);
6965   if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
6966       height == 0) {
6967     return -1;
6968   }
6969   // Negative height means invert the image.
6970   if (height < 0) {
6971     height = -height;
6972     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
6973     dst_stride_argb = -dst_stride_argb;
6974   }
6975 #if defined(HAS_I444ALPHATOARGBROW_SSSE3)
6976   if (TestCpuFlag(kCpuHasSSSE3)) {
6977     I444AlphaToARGBRow = I444AlphaToARGBRow_Any_SSSE3;
6978     if (IS_ALIGNED(width, 8)) {
6979       I444AlphaToARGBRow = I444AlphaToARGBRow_SSSE3;
6980     }
6981   }
6982 #endif
6983 #if defined(HAS_I444ALPHATOARGBROW_AVX2)
6984   if (TestCpuFlag(kCpuHasAVX2)) {
6985     I444AlphaToARGBRow = I444AlphaToARGBRow_Any_AVX2;
6986     if (IS_ALIGNED(width, 16)) {
6987       I444AlphaToARGBRow = I444AlphaToARGBRow_AVX2;
6988     }
6989   }
6990 #endif
6991 #if defined(HAS_I444ALPHATOARGBROW_NEON)
6992   if (TestCpuFlag(kCpuHasNEON)) {
6993     I444AlphaToARGBRow = I444AlphaToARGBRow_Any_NEON;
6994     if (IS_ALIGNED(width, 8)) {
6995       I444AlphaToARGBRow = I444AlphaToARGBRow_NEON;
6996     }
6997   }
6998 #endif
6999 #if defined(HAS_I444ALPHATOARGBROW_MSA)
7000   if (TestCpuFlag(kCpuHasMSA)) {
7001     I444AlphaToARGBRow = I444AlphaToARGBRow_Any_MSA;
7002     if (IS_ALIGNED(width, 8)) {
7003       I444AlphaToARGBRow = I444AlphaToARGBRow_MSA;
7004     }
7005   }
7006 #endif
7007 #if defined(HAS_I444ALPHATOARGBROW_LASX)
7008   if (TestCpuFlag(kCpuHasLASX)) {
7009     I444AlphaToARGBRow = I444AlphaToARGBRow_Any_LASX;
7010     if (IS_ALIGNED(width, 16)) {
7011       I444AlphaToARGBRow = I444AlphaToARGBRow_LASX;
7012     }
7013   }
7014 #endif
7015 #if defined(HAS_I444ALPHATOARGBROW_RVV)
7016   if (TestCpuFlag(kCpuHasRVV)) {
7017     I444AlphaToARGBRow = I444AlphaToARGBRow_RVV;
7018   }
7019 #endif
7020 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
7021   if (TestCpuFlag(kCpuHasSSSE3)) {
7022     ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
7023     if (IS_ALIGNED(width, 4)) {
7024       ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
7025     }
7026   }
7027 #endif
7028 #if defined(HAS_ARGBATTENUATEROW_AVX2)
7029   if (TestCpuFlag(kCpuHasAVX2)) {
7030     ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
7031     if (IS_ALIGNED(width, 8)) {
7032       ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
7033     }
7034   }
7035 #endif
7036 #if defined(HAS_ARGBATTENUATEROW_NEON)
7037   if (TestCpuFlag(kCpuHasNEON)) {
7038     ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
7039     if (IS_ALIGNED(width, 8)) {
7040       ARGBAttenuateRow = ARGBAttenuateRow_NEON;
7041     }
7042   }
7043 #endif
7044 #if defined(HAS_ARGBATTENUATEROW_MSA)
7045   if (TestCpuFlag(kCpuHasMSA)) {
7046     ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
7047     if (IS_ALIGNED(width, 8)) {
7048       ARGBAttenuateRow = ARGBAttenuateRow_MSA;
7049     }
7050   }
7051 #endif
7052 #if defined(HAS_ARGBATTENUATEROW_RVV)
7053   if (TestCpuFlag(kCpuHasRVV)) {
7054     ARGBAttenuateRow = ARGBAttenuateRow_RVV;
7055   }
7056 #endif
7057 
7058 #if defined(HAS_SCALEROWUP2_BILINEAR_SSE2)
7059   if (TestCpuFlag(kCpuHasSSE2)) {
7060     Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_SSE2;
7061     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSE2;
7062   }
7063 #endif
7064 
7065 #if defined(HAS_SCALEROWUP2_BILINEAR_SSSE3)
7066   if (TestCpuFlag(kCpuHasSSSE3)) {
7067     Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_SSSE3;
7068     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSSE3;
7069   }
7070 #endif
7071 
7072 #if defined(HAS_SCALEROWUP2_BILINEAR_AVX2)
7073   if (TestCpuFlag(kCpuHasAVX2)) {
7074     Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_AVX2;
7075     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_AVX2;
7076   }
7077 #endif
7078 
7079 #if defined(HAS_SCALEROWUP2_BILINEAR_NEON)
7080   if (TestCpuFlag(kCpuHasNEON)) {
7081     Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_Any_NEON;
7082     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_NEON;
7083   }
7084 #endif
7085 #if defined(HAS_SCALEROWUP2_BILINEAR_RVV)
7086   if (TestCpuFlag(kCpuHasRVV)) {
7087     Scale2RowUp_Bilinear = ScaleRowUp2_Bilinear_RVV;
7088     ScaleRowUp2_Linear = ScaleRowUp2_Linear_RVV;
7089   }
7090 #endif
7091 
7092   // alloc 4 lines temp
7093   const int row_size = (width + 31) & ~31;
7094   align_buffer_64(row, row_size * 4);
7095   uint8_t* temp_u_1 = row;
7096   uint8_t* temp_u_2 = row + row_size;
7097   uint8_t* temp_v_1 = row + row_size * 2;
7098   uint8_t* temp_v_2 = row + row_size * 3;
7099   if (!row)
7100     return 1;
7101 
7102   ScaleRowUp2_Linear(src_u, temp_u_1, width);
7103   ScaleRowUp2_Linear(src_v, temp_v_1, width);
7104   I444AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
7105                      width);
7106   if (attenuate) {
7107     ARGBAttenuateRow(dst_argb, dst_argb, width);
7108   }
7109   dst_argb += dst_stride_argb;
7110   src_y += src_stride_y;
7111   src_a += src_stride_a;
7112 
7113   for (y = 0; y < height - 2; y += 2) {
7114     Scale2RowUp_Bilinear(src_u, src_stride_u, temp_u_1, row_size, width);
7115     Scale2RowUp_Bilinear(src_v, src_stride_v, temp_v_1, row_size, width);
7116     I444AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
7117                        width);
7118     if (attenuate) {
7119       ARGBAttenuateRow(dst_argb, dst_argb, width);
7120     }
7121     dst_argb += dst_stride_argb;
7122     src_y += src_stride_y;
7123     src_a += src_stride_a;
7124     I444AlphaToARGBRow(src_y, temp_u_2, temp_v_2, src_a, dst_argb, yuvconstants,
7125                        width);
7126     if (attenuate) {
7127       ARGBAttenuateRow(dst_argb, dst_argb, width);
7128     }
7129     dst_argb += dst_stride_argb;
7130     src_y += src_stride_y;
7131     src_u += src_stride_u;
7132     src_v += src_stride_v;
7133     src_a += src_stride_a;
7134   }
7135 
7136   if (!(height & 1)) {
7137     ScaleRowUp2_Linear(src_u, temp_u_1, width);
7138     ScaleRowUp2_Linear(src_v, temp_v_1, width);
7139     I444AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
7140                        width);
7141     if (attenuate) {
7142       ARGBAttenuateRow(dst_argb, dst_argb, width);
7143     }
7144   }
7145 
7146   free_aligned_buffer_64(row);
7147   return 0;
7148 }
7149 
I422AlphaToARGBMatrixLinear(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,const uint8_t * src_a,int src_stride_a,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,int attenuate)7150 static int I422AlphaToARGBMatrixLinear(const uint8_t* src_y,
7151                                        int src_stride_y,
7152                                        const uint8_t* src_u,
7153                                        int src_stride_u,
7154                                        const uint8_t* src_v,
7155                                        int src_stride_v,
7156                                        const uint8_t* src_a,
7157                                        int src_stride_a,
7158                                        uint8_t* dst_argb,
7159                                        int dst_stride_argb,
7160                                        const struct YuvConstants* yuvconstants,
7161                                        int width,
7162                                        int height,
7163                                        int attenuate) {
7164   int y;
7165   void (*I444AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
7166                              const uint8_t* v_buf, const uint8_t* a_buf,
7167                              uint8_t* dst_argb,
7168                              const struct YuvConstants* yuvconstants,
7169                              int width) = I444AlphaToARGBRow_C;
7170   void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
7171                            int width) = ARGBAttenuateRow_C;
7172   void (*ScaleRowUp2_Linear)(const uint8_t* src_ptr, uint8_t* dst_ptr,
7173                              int dst_width) = ScaleRowUp2_Linear_Any_C;
7174   assert(yuvconstants);
7175   if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
7176       height == 0) {
7177     return -1;
7178   }
7179   // Negative height means invert the image.
7180   if (height < 0) {
7181     height = -height;
7182     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
7183     dst_stride_argb = -dst_stride_argb;
7184   }
7185 #if defined(HAS_I444ALPHATOARGBROW_SSSE3)
7186   if (TestCpuFlag(kCpuHasSSSE3)) {
7187     I444AlphaToARGBRow = I444AlphaToARGBRow_Any_SSSE3;
7188     if (IS_ALIGNED(width, 8)) {
7189       I444AlphaToARGBRow = I444AlphaToARGBRow_SSSE3;
7190     }
7191   }
7192 #endif
7193 #if defined(HAS_I444ALPHATOARGBROW_AVX2)
7194   if (TestCpuFlag(kCpuHasAVX2)) {
7195     I444AlphaToARGBRow = I444AlphaToARGBRow_Any_AVX2;
7196     if (IS_ALIGNED(width, 16)) {
7197       I444AlphaToARGBRow = I444AlphaToARGBRow_AVX2;
7198     }
7199   }
7200 #endif
7201 #if defined(HAS_I444ALPHATOARGBROW_NEON)
7202   if (TestCpuFlag(kCpuHasNEON)) {
7203     I444AlphaToARGBRow = I444AlphaToARGBRow_Any_NEON;
7204     if (IS_ALIGNED(width, 8)) {
7205       I444AlphaToARGBRow = I444AlphaToARGBRow_NEON;
7206     }
7207   }
7208 #endif
7209 #if defined(HAS_I444ALPHATOARGBROW_MSA)
7210   if (TestCpuFlag(kCpuHasMSA)) {
7211     I444AlphaToARGBRow = I444AlphaToARGBRow_Any_MSA;
7212     if (IS_ALIGNED(width, 8)) {
7213       I444AlphaToARGBRow = I444AlphaToARGBRow_MSA;
7214     }
7215   }
7216 #endif
7217 #if defined(HAS_I444ALPHATOARGBROW_LASX)
7218   if (TestCpuFlag(kCpuHasLASX)) {
7219     I444AlphaToARGBRow = I444AlphaToARGBRow_Any_LASX;
7220     if (IS_ALIGNED(width, 16)) {
7221       I444AlphaToARGBRow = I444AlphaToARGBRow_LASX;
7222     }
7223   }
7224 #endif
7225 #if defined(HAS_I444ALPHATOARGBROW_RVV)
7226   if (TestCpuFlag(kCpuHasRVV)) {
7227     I444AlphaToARGBRow = I444AlphaToARGBRow_RVV;
7228   }
7229 #endif
7230 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
7231   if (TestCpuFlag(kCpuHasSSSE3)) {
7232     ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
7233     if (IS_ALIGNED(width, 4)) {
7234       ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
7235     }
7236   }
7237 #endif
7238 #if defined(HAS_ARGBATTENUATEROW_AVX2)
7239   if (TestCpuFlag(kCpuHasAVX2)) {
7240     ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
7241     if (IS_ALIGNED(width, 8)) {
7242       ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
7243     }
7244   }
7245 #endif
7246 #if defined(HAS_ARGBATTENUATEROW_NEON)
7247   if (TestCpuFlag(kCpuHasNEON)) {
7248     ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
7249     if (IS_ALIGNED(width, 8)) {
7250       ARGBAttenuateRow = ARGBAttenuateRow_NEON;
7251     }
7252   }
7253 #endif
7254 #if defined(HAS_ARGBATTENUATEROW_MSA)
7255   if (TestCpuFlag(kCpuHasMSA)) {
7256     ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
7257     if (IS_ALIGNED(width, 8)) {
7258       ARGBAttenuateRow = ARGBAttenuateRow_MSA;
7259     }
7260   }
7261 #endif
7262 #if defined(HAS_ARGBATTENUATEROW_RVV)
7263   if (TestCpuFlag(kCpuHasRVV)) {
7264     ARGBAttenuateRow = ARGBAttenuateRow_RVV;
7265   }
7266 #endif
7267 
7268 #if defined(HAS_SCALEROWUP2_LINEAR_SSE2)
7269   if (TestCpuFlag(kCpuHasSSE2)) {
7270     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSE2;
7271   }
7272 #endif
7273 #if defined(HAS_SCALEROWUP2_LINEAR_SSSE3)
7274   if (TestCpuFlag(kCpuHasSSSE3)) {
7275     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSSE3;
7276   }
7277 #endif
7278 #if defined(HAS_SCALEROWUP2_LINEAR_AVX2)
7279   if (TestCpuFlag(kCpuHasAVX2)) {
7280     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_AVX2;
7281   }
7282 #endif
7283 #if defined(HAS_SCALEROWUP2_LINEAR_NEON)
7284   if (TestCpuFlag(kCpuHasNEON)) {
7285     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_NEON;
7286   }
7287 #endif
7288 #if defined(HAS_SCALEROWUP2_LINEAR_RVV)
7289   if (TestCpuFlag(kCpuHasRVV)) {
7290     ScaleRowUp2_Linear = ScaleRowUp2_Linear_RVV;
7291   }
7292 #endif
7293 
7294   // alloc 2 lines temp
7295   const int row_size = (width + 31) & ~31;
7296   align_buffer_64(row, row_size * 2);
7297   uint8_t* temp_u = row;
7298   uint8_t* temp_v = row + row_size;
7299   if (!row)
7300     return 1;
7301 
7302   for (y = 0; y < height; ++y) {
7303     ScaleRowUp2_Linear(src_u, temp_u, width);
7304     ScaleRowUp2_Linear(src_v, temp_v, width);
7305     I444AlphaToARGBRow(src_y, temp_u, temp_v, src_a, dst_argb, yuvconstants,
7306                        width);
7307     if (attenuate) {
7308       ARGBAttenuateRow(dst_argb, dst_argb, width);
7309     }
7310     dst_argb += dst_stride_argb;
7311     src_a += src_stride_a;
7312     src_y += src_stride_y;
7313     src_u += src_stride_u;
7314     src_v += src_stride_v;
7315   }
7316 
7317   free_aligned_buffer_64(row);
7318   return 0;
7319 }
7320 
I010AlphaToARGBMatrixBilinear(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,const uint16_t * src_a,int src_stride_a,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,int attenuate)7321 static int I010AlphaToARGBMatrixBilinear(
7322     const uint16_t* src_y,
7323     int src_stride_y,
7324     const uint16_t* src_u,
7325     int src_stride_u,
7326     const uint16_t* src_v,
7327     int src_stride_v,
7328     const uint16_t* src_a,
7329     int src_stride_a,
7330     uint8_t* dst_argb,
7331     int dst_stride_argb,
7332     const struct YuvConstants* yuvconstants,
7333     int width,
7334     int height,
7335     int attenuate) {
7336   int y;
7337   void (*I410AlphaToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
7338                              const uint16_t* v_buf, const uint16_t* a_buf,
7339                              uint8_t* dst_argb,
7340                              const struct YuvConstants* yuvconstants,
7341                              int width) = I410AlphaToARGBRow_C;
7342   void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
7343                            int width) = ARGBAttenuateRow_C;
7344   void (*Scale2RowUp_Bilinear_12)(
7345       const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr,
7346       ptrdiff_t dst_stride, int dst_width) = ScaleRowUp2_Bilinear_16_Any_C;
7347   void (*ScaleRowUp2_Linear_12)(const uint16_t* src_ptr, uint16_t* dst_ptr,
7348                                 int dst_width) = ScaleRowUp2_Linear_16_Any_C;
7349   assert(yuvconstants);
7350   if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
7351       height == 0) {
7352     return -1;
7353   }
7354   // Negative height means invert the image.
7355   if (height < 0) {
7356     height = -height;
7357     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
7358     dst_stride_argb = -dst_stride_argb;
7359   }
7360 #if defined(HAS_I410ALPHATOARGBROW_SSSE3)
7361   if (TestCpuFlag(kCpuHasSSSE3)) {
7362     I410AlphaToARGBRow = I410AlphaToARGBRow_Any_SSSE3;
7363     if (IS_ALIGNED(width, 8)) {
7364       I410AlphaToARGBRow = I410AlphaToARGBRow_SSSE3;
7365     }
7366   }
7367 #endif
7368 #if defined(HAS_I410ALPHATOARGBROW_AVX2)
7369   if (TestCpuFlag(kCpuHasAVX2)) {
7370     I410AlphaToARGBRow = I410AlphaToARGBRow_Any_AVX2;
7371     if (IS_ALIGNED(width, 16)) {
7372       I410AlphaToARGBRow = I410AlphaToARGBRow_AVX2;
7373     }
7374   }
7375 #endif
7376 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
7377   if (TestCpuFlag(kCpuHasSSSE3)) {
7378     ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
7379     if (IS_ALIGNED(width, 4)) {
7380       ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
7381     }
7382   }
7383 #endif
7384 #if defined(HAS_ARGBATTENUATEROW_AVX2)
7385   if (TestCpuFlag(kCpuHasAVX2)) {
7386     ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
7387     if (IS_ALIGNED(width, 8)) {
7388       ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
7389     }
7390   }
7391 #endif
7392 #if defined(HAS_ARGBATTENUATEROW_NEON)
7393   if (TestCpuFlag(kCpuHasNEON)) {
7394     ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
7395     if (IS_ALIGNED(width, 8)) {
7396       ARGBAttenuateRow = ARGBAttenuateRow_NEON;
7397     }
7398   }
7399 #endif
7400 #if defined(HAS_ARGBATTENUATEROW_MSA)
7401   if (TestCpuFlag(kCpuHasMSA)) {
7402     ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
7403     if (IS_ALIGNED(width, 8)) {
7404       ARGBAttenuateRow = ARGBAttenuateRow_MSA;
7405     }
7406   }
7407 #endif
7408 #if defined(HAS_ARGBATTENUATEROW_RVV)
7409   if (TestCpuFlag(kCpuHasRVV)) {
7410     ARGBAttenuateRow = ARGBAttenuateRow_RVV;
7411   }
7412 #endif
7413 
7414 #if defined(HAS_SCALEROWUP2_BILINEAR_12_SSSE3)
7415   if (TestCpuFlag(kCpuHasSSSE3)) {
7416     Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_SSSE3;
7417     ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_SSSE3;
7418   }
7419 #endif
7420 
7421 #if defined(HAS_SCALEROWUP2_BILINEAR_12_AVX2)
7422   if (TestCpuFlag(kCpuHasAVX2)) {
7423     Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_AVX2;
7424     ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_AVX2;
7425   }
7426 #endif
7427 
7428 #if defined(HAS_SCALEROWUP2_BILINEAR_12_NEON)
7429   if (TestCpuFlag(kCpuHasNEON)) {
7430     Scale2RowUp_Bilinear_12 = ScaleRowUp2_Bilinear_12_Any_NEON;
7431     ScaleRowUp2_Linear_12 = ScaleRowUp2_Linear_12_Any_NEON;
7432   }
7433 #endif
7434 
7435   // alloc 4 lines temp
7436   const int row_size = (width + 31) & ~31;
7437   align_buffer_64(row, row_size * 4 * sizeof(uint16_t));
7438   uint16_t* temp_u_1 = (uint16_t*)(row);
7439   uint16_t* temp_u_2 = (uint16_t*)(row) + row_size;
7440   uint16_t* temp_v_1 = (uint16_t*)(row) + row_size * 2;
7441   uint16_t* temp_v_2 = (uint16_t*)(row) + row_size * 3;
7442   if (!row)
7443     return 1;
7444 
7445   ScaleRowUp2_Linear_12(src_u, temp_u_1, width);
7446   ScaleRowUp2_Linear_12(src_v, temp_v_1, width);
7447   I410AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
7448                      width);
7449   if (attenuate) {
7450     ARGBAttenuateRow(dst_argb, dst_argb, width);
7451   }
7452   dst_argb += dst_stride_argb;
7453   src_y += src_stride_y;
7454   src_a += src_stride_a;
7455 
7456   for (y = 0; y < height - 2; y += 2) {
7457     Scale2RowUp_Bilinear_12(src_u, src_stride_u, temp_u_1, row_size, width);
7458     Scale2RowUp_Bilinear_12(src_v, src_stride_v, temp_v_1, row_size, width);
7459     I410AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
7460                        width);
7461     if (attenuate) {
7462       ARGBAttenuateRow(dst_argb, dst_argb, width);
7463     }
7464     dst_argb += dst_stride_argb;
7465     src_y += src_stride_y;
7466     src_a += src_stride_a;
7467     I410AlphaToARGBRow(src_y, temp_u_2, temp_v_2, src_a, dst_argb, yuvconstants,
7468                        width);
7469     if (attenuate) {
7470       ARGBAttenuateRow(dst_argb, dst_argb, width);
7471     }
7472     dst_argb += dst_stride_argb;
7473     src_y += src_stride_y;
7474     src_a += src_stride_a;
7475     src_u += src_stride_u;
7476     src_v += src_stride_v;
7477   }
7478 
7479   if (!(height & 1)) {
7480     ScaleRowUp2_Linear_12(src_u, temp_u_1, width);
7481     ScaleRowUp2_Linear_12(src_v, temp_v_1, width);
7482     I410AlphaToARGBRow(src_y, temp_u_1, temp_v_1, src_a, dst_argb, yuvconstants,
7483                        width);
7484     if (attenuate) {
7485       ARGBAttenuateRow(dst_argb, dst_argb, width);
7486     }
7487   }
7488 
7489   free_aligned_buffer_64(row);
7490   return 0;
7491 }
7492 
I210AlphaToARGBMatrixLinear(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,const uint16_t * src_a,int src_stride_a,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,int attenuate)7493 static int I210AlphaToARGBMatrixLinear(const uint16_t* src_y,
7494                                        int src_stride_y,
7495                                        const uint16_t* src_u,
7496                                        int src_stride_u,
7497                                        const uint16_t* src_v,
7498                                        int src_stride_v,
7499                                        const uint16_t* src_a,
7500                                        int src_stride_a,
7501                                        uint8_t* dst_argb,
7502                                        int dst_stride_argb,
7503                                        const struct YuvConstants* yuvconstants,
7504                                        int width,
7505                                        int height,
7506                                        int attenuate) {
7507   int y;
7508   void (*I410AlphaToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
7509                              const uint16_t* v_buf, const uint16_t* a_buf,
7510                              uint8_t* dst_argb,
7511                              const struct YuvConstants* yuvconstants,
7512                              int width) = I410AlphaToARGBRow_C;
7513   void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
7514                            int width) = ARGBAttenuateRow_C;
7515   void (*ScaleRowUp2_Linear)(const uint16_t* src_ptr, uint16_t* dst_ptr,
7516                              int dst_width) = ScaleRowUp2_Linear_16_Any_C;
7517   assert(yuvconstants);
7518   if (!src_y || !src_u || !src_v || !src_a || !dst_argb || width <= 0 ||
7519       height == 0) {
7520     return -1;
7521   }
7522   // Negative height means invert the image.
7523   if (height < 0) {
7524     height = -height;
7525     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
7526     dst_stride_argb = -dst_stride_argb;
7527   }
7528 #if defined(HAS_I410ALPHATOARGBROW_SSSE3)
7529   if (TestCpuFlag(kCpuHasSSSE3)) {
7530     I410AlphaToARGBRow = I410AlphaToARGBRow_Any_SSSE3;
7531     if (IS_ALIGNED(width, 8)) {
7532       I410AlphaToARGBRow = I410AlphaToARGBRow_SSSE3;
7533     }
7534   }
7535 #endif
7536 #if defined(HAS_I410ALPHATOARGBROW_AVX2)
7537   if (TestCpuFlag(kCpuHasAVX2)) {
7538     I410AlphaToARGBRow = I410AlphaToARGBRow_Any_AVX2;
7539     if (IS_ALIGNED(width, 16)) {
7540       I410AlphaToARGBRow = I410AlphaToARGBRow_AVX2;
7541     }
7542   }
7543 #endif
7544 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
7545   if (TestCpuFlag(kCpuHasSSSE3)) {
7546     ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
7547     if (IS_ALIGNED(width, 4)) {
7548       ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
7549     }
7550   }
7551 #endif
7552 #if defined(HAS_ARGBATTENUATEROW_AVX2)
7553   if (TestCpuFlag(kCpuHasAVX2)) {
7554     ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
7555     if (IS_ALIGNED(width, 8)) {
7556       ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
7557     }
7558   }
7559 #endif
7560 #if defined(HAS_ARGBATTENUATEROW_NEON)
7561   if (TestCpuFlag(kCpuHasNEON)) {
7562     ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
7563     if (IS_ALIGNED(width, 8)) {
7564       ARGBAttenuateRow = ARGBAttenuateRow_NEON;
7565     }
7566   }
7567 #endif
7568 #if defined(HAS_ARGBATTENUATEROW_MSA)
7569   if (TestCpuFlag(kCpuHasMSA)) {
7570     ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
7571     if (IS_ALIGNED(width, 8)) {
7572       ARGBAttenuateRow = ARGBAttenuateRow_MSA;
7573     }
7574   }
7575 #endif
7576 #if defined(HAS_ARGBATTENUATEROW_RVV)
7577   if (TestCpuFlag(kCpuHasRVV)) {
7578     ARGBAttenuateRow = ARGBAttenuateRow_RVV;
7579   }
7580 #endif
7581 
7582 #if defined(HAS_SCALEROWUP2_LINEAR_12_SSSE3)
7583   if (TestCpuFlag(kCpuHasSSSE3)) {
7584     ScaleRowUp2_Linear = ScaleRowUp2_Linear_12_Any_SSSE3;
7585   }
7586 #endif
7587 #if defined(HAS_SCALEROWUP2_LINEAR_12_AVX2)
7588   if (TestCpuFlag(kCpuHasAVX2)) {
7589     ScaleRowUp2_Linear = ScaleRowUp2_Linear_12_Any_AVX2;
7590   }
7591 #endif
7592 #if defined(HAS_SCALEROWUP2_LINEAR_12_NEON)
7593   if (TestCpuFlag(kCpuHasNEON)) {
7594     ScaleRowUp2_Linear = ScaleRowUp2_Linear_12_Any_NEON;
7595   }
7596 #endif
7597 
7598   // alloc 2 lines temp
7599   const int row_size = (width + 31) & ~31;
7600   align_buffer_64(row, row_size * 2 * sizeof(uint16_t));
7601   uint16_t* temp_u = (uint16_t*)(row);
7602   uint16_t* temp_v = (uint16_t*)(row) + row_size;
7603   if (!row)
7604     return 1;
7605 
7606   for (y = 0; y < height; ++y) {
7607     ScaleRowUp2_Linear(src_u, temp_u, width);
7608     ScaleRowUp2_Linear(src_v, temp_v, width);
7609     I410AlphaToARGBRow(src_y, temp_u, temp_v, src_a, dst_argb, yuvconstants,
7610                        width);
7611     if (attenuate) {
7612       ARGBAttenuateRow(dst_argb, dst_argb, width);
7613     }
7614     dst_argb += dst_stride_argb;
7615     src_a += src_stride_a;
7616     src_y += src_stride_y;
7617     src_u += src_stride_u;
7618     src_v += src_stride_v;
7619   }
7620   free_aligned_buffer_64(row);
7621   return 0;
7622 }
7623 
P010ToARGBMatrixBilinear(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)7624 static int P010ToARGBMatrixBilinear(const uint16_t* src_y,
7625                                     int src_stride_y,
7626                                     const uint16_t* src_uv,
7627                                     int src_stride_uv,
7628                                     uint8_t* dst_argb,
7629                                     int dst_stride_argb,
7630                                     const struct YuvConstants* yuvconstants,
7631                                     int width,
7632                                     int height) {
7633   int y;
7634   void (*P410ToARGBRow)(
7635       const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
7636       const struct YuvConstants* yuvconstants, int width) = P410ToARGBRow_C;
7637   void (*Scale2RowUp_Bilinear_16)(
7638       const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr,
7639       ptrdiff_t dst_stride, int dst_width) = ScaleUVRowUp2_Bilinear_16_Any_C;
7640   assert(yuvconstants);
7641   if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
7642     return -1;
7643   }
7644   // Negative height means invert the image.
7645   if (height < 0) {
7646     height = -height;
7647     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
7648     dst_stride_argb = -dst_stride_argb;
7649   }
7650 #if defined(HAS_P410TOARGBROW_SSSE3)
7651   if (TestCpuFlag(kCpuHasSSSE3)) {
7652     P410ToARGBRow = P410ToARGBRow_Any_SSSE3;
7653     if (IS_ALIGNED(width, 8)) {
7654       P410ToARGBRow = P410ToARGBRow_SSSE3;
7655     }
7656   }
7657 #endif
7658 #if defined(HAS_P410TOARGBROW_AVX2)
7659   if (TestCpuFlag(kCpuHasAVX2)) {
7660     P410ToARGBRow = P410ToARGBRow_Any_AVX2;
7661     if (IS_ALIGNED(width, 16)) {
7662       P410ToARGBRow = P410ToARGBRow_AVX2;
7663     }
7664   }
7665 #endif
7666 
7667 #ifdef HAS_SCALEUVROWUP2_BILINEAR_16_SSE41
7668   if (TestCpuFlag(kCpuHasSSE41)) {
7669     Scale2RowUp_Bilinear_16 = ScaleUVRowUp2_Bilinear_16_Any_SSE41;
7670   }
7671 #endif
7672 
7673 #ifdef HAS_SCALEUVROWUP2_BILINEAR_16_AVX2
7674   if (TestCpuFlag(kCpuHasAVX2)) {
7675     Scale2RowUp_Bilinear_16 = ScaleUVRowUp2_Bilinear_16_Any_AVX2;
7676   }
7677 #endif
7678 
7679 #ifdef HAS_SCALEUVROWUP2_BILINEAR_16_NEON
7680   if (TestCpuFlag(kCpuHasNEON)) {
7681     Scale2RowUp_Bilinear_16 = ScaleUVRowUp2_Bilinear_16_Any_NEON;
7682   }
7683 #endif
7684 
7685   // alloc 2 lines temp
7686   const int row_size = (2 * width + 31) & ~31;
7687   align_buffer_64(row, row_size * 2 * sizeof(uint16_t));
7688   uint16_t* temp_uv_1 = (uint16_t*)(row);
7689   uint16_t* temp_uv_2 = (uint16_t*)(row) + row_size;
7690   if (!row)
7691     return 1;
7692 
7693   Scale2RowUp_Bilinear_16(src_uv, 0, temp_uv_1, row_size, width);
7694   P410ToARGBRow(src_y, temp_uv_1, dst_argb, yuvconstants, width);
7695   dst_argb += dst_stride_argb;
7696   src_y += src_stride_y;
7697 
7698   for (y = 0; y < height - 2; y += 2) {
7699     Scale2RowUp_Bilinear_16(src_uv, src_stride_uv, temp_uv_1, row_size, width);
7700     P410ToARGBRow(src_y, temp_uv_1, dst_argb, yuvconstants, width);
7701     dst_argb += dst_stride_argb;
7702     src_y += src_stride_y;
7703     P410ToARGBRow(src_y, temp_uv_2, dst_argb, yuvconstants, width);
7704     dst_argb += dst_stride_argb;
7705     src_y += src_stride_y;
7706     src_uv += src_stride_uv;
7707   }
7708 
7709   if (!(height & 1)) {
7710     Scale2RowUp_Bilinear_16(src_uv, 0, temp_uv_1, row_size, width);
7711     P410ToARGBRow(src_y, temp_uv_1, dst_argb, yuvconstants, width);
7712   }
7713 
7714   free_aligned_buffer_64(row);
7715   return 0;
7716 }
7717 
P210ToARGBMatrixLinear(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height)7718 static int P210ToARGBMatrixLinear(const uint16_t* src_y,
7719                                   int src_stride_y,
7720                                   const uint16_t* src_uv,
7721                                   int src_stride_uv,
7722                                   uint8_t* dst_argb,
7723                                   int dst_stride_argb,
7724                                   const struct YuvConstants* yuvconstants,
7725                                   int width,
7726                                   int height) {
7727   int y;
7728   void (*P410ToARGBRow)(
7729       const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
7730       const struct YuvConstants* yuvconstants, int width) = P410ToARGBRow_C;
7731   void (*ScaleRowUp2_Linear)(const uint16_t* src_uv, uint16_t* dst_uv,
7732                              int dst_width) = ScaleUVRowUp2_Linear_16_Any_C;
7733   assert(yuvconstants);
7734   if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
7735     return -1;
7736   }
7737   // Negative height means invert the image.
7738   if (height < 0) {
7739     height = -height;
7740     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
7741     dst_stride_argb = -dst_stride_argb;
7742   }
7743 #if defined(HAS_P410TOARGBROW_SSSE3)
7744   if (TestCpuFlag(kCpuHasSSSE3)) {
7745     P410ToARGBRow = P410ToARGBRow_Any_SSSE3;
7746     if (IS_ALIGNED(width, 8)) {
7747       P410ToARGBRow = P410ToARGBRow_SSSE3;
7748     }
7749   }
7750 #endif
7751 #if defined(HAS_P410TOARGBROW_AVX2)
7752   if (TestCpuFlag(kCpuHasAVX2)) {
7753     P410ToARGBRow = P410ToARGBRow_Any_AVX2;
7754     if (IS_ALIGNED(width, 16)) {
7755       P410ToARGBRow = P410ToARGBRow_AVX2;
7756     }
7757   }
7758 #endif
7759 
7760 #ifdef HAS_SCALEUVROWUP2_LINEAR_16_SSE41
7761   if (TestCpuFlag(kCpuHasSSE41)) {
7762     ScaleRowUp2_Linear = ScaleUVRowUp2_Linear_16_Any_SSE41;
7763   }
7764 #endif
7765 
7766 #ifdef HAS_SCALEUVROWUP2_LINEAR_16_AVX2
7767   if (TestCpuFlag(kCpuHasAVX2)) {
7768     ScaleRowUp2_Linear = ScaleUVRowUp2_Linear_16_Any_AVX2;
7769   }
7770 #endif
7771 
7772 #ifdef HAS_SCALEUVROWUP2_LINEAR_16_NEON
7773   if (TestCpuFlag(kCpuHasNEON)) {
7774     ScaleRowUp2_Linear = ScaleUVRowUp2_Linear_16_Any_NEON;
7775   }
7776 #endif
7777 
7778   const int row_size = (2 * width + 31) & ~31;
7779   align_buffer_64(row, row_size * sizeof(uint16_t));
7780   uint16_t* temp_uv = (uint16_t*)(row);
7781   if (!row)
7782     return 1;
7783 
7784   for (y = 0; y < height; ++y) {
7785     ScaleRowUp2_Linear(src_uv, temp_uv, width);
7786     P410ToARGBRow(src_y, temp_uv, dst_argb, yuvconstants, width);
7787     dst_argb += dst_stride_argb;
7788     src_y += src_stride_y;
7789     src_uv += src_stride_uv;
7790   }
7791 
7792   free_aligned_buffer_64(row);
7793   return 0;
7794 }
7795 
P010ToAR30MatrixBilinear(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height)7796 static int P010ToAR30MatrixBilinear(const uint16_t* src_y,
7797                                     int src_stride_y,
7798                                     const uint16_t* src_uv,
7799                                     int src_stride_uv,
7800                                     uint8_t* dst_ar30,
7801                                     int dst_stride_ar30,
7802                                     const struct YuvConstants* yuvconstants,
7803                                     int width,
7804                                     int height) {
7805   int y;
7806   void (*P410ToAR30Row)(
7807       const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
7808       const struct YuvConstants* yuvconstants, int width) = P410ToAR30Row_C;
7809   void (*Scale2RowUp_Bilinear_16)(
7810       const uint16_t* src_ptr, ptrdiff_t src_stride, uint16_t* dst_ptr,
7811       ptrdiff_t dst_stride, int dst_width) = ScaleUVRowUp2_Bilinear_16_Any_C;
7812   assert(yuvconstants);
7813   if (!src_y || !src_uv || !dst_ar30 || width <= 0 || height == 0) {
7814     return -1;
7815   }
7816   // Negative height means invert the image.
7817   if (height < 0) {
7818     height = -height;
7819     dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
7820     dst_stride_ar30 = -dst_stride_ar30;
7821   }
7822 #if defined(HAS_P410TOAR30ROW_SSSE3)
7823   if (TestCpuFlag(kCpuHasSSSE3)) {
7824     P410ToAR30Row = P410ToAR30Row_Any_SSSE3;
7825     if (IS_ALIGNED(width, 8)) {
7826       P410ToAR30Row = P410ToAR30Row_SSSE3;
7827     }
7828   }
7829 #endif
7830 #if defined(HAS_P410TOAR30ROW_AVX2)
7831   if (TestCpuFlag(kCpuHasAVX2)) {
7832     P410ToAR30Row = P410ToAR30Row_Any_AVX2;
7833     if (IS_ALIGNED(width, 16)) {
7834       P410ToAR30Row = P410ToAR30Row_AVX2;
7835     }
7836   }
7837 #endif
7838 
7839 #ifdef HAS_SCALEUVROWUP2_BILINEAR_16_SSE41
7840   if (TestCpuFlag(kCpuHasSSE41)) {
7841     Scale2RowUp_Bilinear_16 = ScaleUVRowUp2_Bilinear_16_Any_SSE41;
7842   }
7843 #endif
7844 
7845 #ifdef HAS_SCALEUVROWUP2_BILINEAR_16_AVX2
7846   if (TestCpuFlag(kCpuHasAVX2)) {
7847     Scale2RowUp_Bilinear_16 = ScaleUVRowUp2_Bilinear_16_Any_AVX2;
7848   }
7849 #endif
7850 
7851 #ifdef HAS_SCALEUVROWUP2_BILINEAR_16_NEON
7852   if (TestCpuFlag(kCpuHasNEON)) {
7853     Scale2RowUp_Bilinear_16 = ScaleUVRowUp2_Bilinear_16_Any_NEON;
7854   }
7855 #endif
7856 
7857   // alloc 2 lines temp
7858   const int row_size = (2 * width + 31) & ~31;
7859   align_buffer_64(row, row_size * 2 * sizeof(uint16_t));
7860   uint16_t* temp_uv_1 = (uint16_t*)(row);
7861   uint16_t* temp_uv_2 = (uint16_t*)(row) + row_size;
7862   if (!row)
7863     return 1;
7864 
7865   Scale2RowUp_Bilinear_16(src_uv, 0, temp_uv_1, row_size, width);
7866   P410ToAR30Row(src_y, temp_uv_1, dst_ar30, yuvconstants, width);
7867   dst_ar30 += dst_stride_ar30;
7868   src_y += src_stride_y;
7869 
7870   for (y = 0; y < height - 2; y += 2) {
7871     Scale2RowUp_Bilinear_16(src_uv, src_stride_uv, temp_uv_1, row_size, width);
7872     P410ToAR30Row(src_y, temp_uv_1, dst_ar30, yuvconstants, width);
7873     dst_ar30 += dst_stride_ar30;
7874     src_y += src_stride_y;
7875     P410ToAR30Row(src_y, temp_uv_2, dst_ar30, yuvconstants, width);
7876     dst_ar30 += dst_stride_ar30;
7877     src_y += src_stride_y;
7878     src_uv += src_stride_uv;
7879   }
7880 
7881   if (!(height & 1)) {
7882     Scale2RowUp_Bilinear_16(src_uv, 0, temp_uv_1, row_size, width);
7883     P410ToAR30Row(src_y, temp_uv_1, dst_ar30, yuvconstants, width);
7884   }
7885 
7886   free_aligned_buffer_64(row);
7887   return 0;
7888 }
7889 
P210ToAR30MatrixLinear(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height)7890 static int P210ToAR30MatrixLinear(const uint16_t* src_y,
7891                                   int src_stride_y,
7892                                   const uint16_t* src_uv,
7893                                   int src_stride_uv,
7894                                   uint8_t* dst_ar30,
7895                                   int dst_stride_ar30,
7896                                   const struct YuvConstants* yuvconstants,
7897                                   int width,
7898                                   int height) {
7899   int y;
7900   void (*P410ToAR30Row)(
7901       const uint16_t* y_buf, const uint16_t* uv_buf, uint8_t* rgb_buf,
7902       const struct YuvConstants* yuvconstants, int width) = P410ToAR30Row_C;
7903   void (*ScaleRowUp2_Linear)(const uint16_t* src_uv, uint16_t* dst_uv,
7904                              int dst_width) = ScaleUVRowUp2_Linear_16_Any_C;
7905   assert(yuvconstants);
7906   if (!src_y || !src_uv || !dst_ar30 || width <= 0 || height == 0) {
7907     return -1;
7908   }
7909   // Negative height means invert the image.
7910   if (height < 0) {
7911     height = -height;
7912     dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
7913     dst_stride_ar30 = -dst_stride_ar30;
7914   }
7915 #if defined(HAS_P410TOAR30ROW_SSSE3)
7916   if (TestCpuFlag(kCpuHasSSSE3)) {
7917     P410ToAR30Row = P410ToAR30Row_Any_SSSE3;
7918     if (IS_ALIGNED(width, 8)) {
7919       P410ToAR30Row = P410ToAR30Row_SSSE3;
7920     }
7921   }
7922 #endif
7923 #if defined(HAS_P410TOAR30ROW_AVX2)
7924   if (TestCpuFlag(kCpuHasAVX2)) {
7925     P410ToAR30Row = P410ToAR30Row_Any_AVX2;
7926     if (IS_ALIGNED(width, 16)) {
7927       P410ToAR30Row = P410ToAR30Row_AVX2;
7928     }
7929   }
7930 #endif
7931 
7932 #ifdef HAS_SCALEUVROWUP2_LINEAR_16_SSE41
7933   if (TestCpuFlag(kCpuHasSSE41)) {
7934     ScaleRowUp2_Linear = ScaleUVRowUp2_Linear_16_Any_SSE41;
7935   }
7936 #endif
7937 
7938 #ifdef HAS_SCALEUVROWUP2_LINEAR_16_AVX2
7939   if (TestCpuFlag(kCpuHasAVX2)) {
7940     ScaleRowUp2_Linear = ScaleUVRowUp2_Linear_16_Any_AVX2;
7941   }
7942 #endif
7943 
7944 #ifdef HAS_SCALEUVROWUP2_LINEAR_16_NEON
7945   if (TestCpuFlag(kCpuHasNEON)) {
7946     ScaleRowUp2_Linear = ScaleUVRowUp2_Linear_16_Any_NEON;
7947   }
7948 #endif
7949 
7950   const int row_size = (2 * width + 31) & ~31;
7951   align_buffer_64(row, row_size * sizeof(uint16_t));
7952   uint16_t* temp_uv = (uint16_t*)(row);
7953   if (!row)
7954     return 1;
7955 
7956   for (y = 0; y < height; ++y) {
7957     ScaleRowUp2_Linear(src_uv, temp_uv, width);
7958     P410ToAR30Row(src_y, temp_uv, dst_ar30, yuvconstants, width);
7959     dst_ar30 += dst_stride_ar30;
7960     src_y += src_stride_y;
7961     src_uv += src_stride_uv;
7962   }
7963 
7964   free_aligned_buffer_64(row);
7965   return 0;
7966 }
7967 
I422ToRGB24MatrixLinear(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgb24,int dst_stride_rgb24,const struct YuvConstants * yuvconstants,int width,int height)7968 static int I422ToRGB24MatrixLinear(const uint8_t* src_y,
7969                                    int src_stride_y,
7970                                    const uint8_t* src_u,
7971                                    int src_stride_u,
7972                                    const uint8_t* src_v,
7973                                    int src_stride_v,
7974                                    uint8_t* dst_rgb24,
7975                                    int dst_stride_rgb24,
7976                                    const struct YuvConstants* yuvconstants,
7977                                    int width,
7978                                    int height) {
7979   int y;
7980   void (*I444ToRGB24Row)(const uint8_t* y_buf, const uint8_t* u_buf,
7981                          const uint8_t* v_buf, uint8_t* rgb_buf,
7982                          const struct YuvConstants* yuvconstants, int width) =
7983       I444ToRGB24Row_C;
7984   void (*ScaleRowUp2_Linear)(const uint8_t* src_ptr, uint8_t* dst_ptr,
7985                              int dst_width) = ScaleRowUp2_Linear_Any_C;
7986   assert(yuvconstants);
7987   if (!src_y || !src_u || !src_v || !dst_rgb24 || width <= 0 || height == 0) {
7988     return -1;
7989   }
7990   // Negative height means invert the image.
7991   if (height < 0) {
7992     height = -height;
7993     dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
7994     dst_stride_rgb24 = -dst_stride_rgb24;
7995   }
7996 #if defined(HAS_I444TORGB24ROW_SSSE3)
7997   if (TestCpuFlag(kCpuHasSSSE3)) {
7998     I444ToRGB24Row = I444ToRGB24Row_Any_SSSE3;
7999     if (IS_ALIGNED(width, 16)) {
8000       I444ToRGB24Row = I444ToRGB24Row_SSSE3;
8001     }
8002   }
8003 #endif
8004 #if defined(HAS_I444TORGB24ROW_AVX2)
8005   if (TestCpuFlag(kCpuHasAVX2)) {
8006     I444ToRGB24Row = I444ToRGB24Row_Any_AVX2;
8007     if (IS_ALIGNED(width, 32)) {
8008       I444ToRGB24Row = I444ToRGB24Row_AVX2;
8009     }
8010   }
8011 #endif
8012 #if defined(HAS_I444TORGB24ROW_NEON)
8013   if (TestCpuFlag(kCpuHasNEON)) {
8014     I444ToRGB24Row = I444ToRGB24Row_Any_NEON;
8015     if (IS_ALIGNED(width, 8)) {
8016       I444ToRGB24Row = I444ToRGB24Row_NEON;
8017     }
8018   }
8019 #endif
8020 #if defined(HAS_I444TORGB24ROW_RVV)
8021   if (TestCpuFlag(kCpuHasRVV)) {
8022     I444ToRGB24Row = I444ToRGB24Row_RVV;
8023   }
8024 #endif
8025 #if defined(HAS_SCALEROWUP2_LINEAR_SSE2)
8026   if (TestCpuFlag(kCpuHasSSE2)) {
8027     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSE2;
8028   }
8029 #endif
8030 #if defined(HAS_SCALEROWUP2_LINEAR_SSSE3)
8031   if (TestCpuFlag(kCpuHasSSSE3)) {
8032     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_SSSE3;
8033   }
8034 #endif
8035 #if defined(HAS_SCALEROWUP2_LINEAR_AVX2)
8036   if (TestCpuFlag(kCpuHasAVX2)) {
8037     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_AVX2;
8038   }
8039 #endif
8040 #if defined(HAS_SCALEROWUP2_LINEAR_NEON)
8041   if (TestCpuFlag(kCpuHasNEON)) {
8042     ScaleRowUp2_Linear = ScaleRowUp2_Linear_Any_NEON;
8043   }
8044 #endif
8045 #if defined(HAS_SCALEROWUP2_LINEAR_RVV)
8046   if (TestCpuFlag(kCpuHasRVV)) {
8047     ScaleRowUp2_Linear = ScaleRowUp2_Linear_RVV;
8048   }
8049 #endif
8050 
8051   // alloc 2 lines temp
8052   const int row_size = (width + 31) & ~31;
8053   align_buffer_64(row, row_size * 2);
8054   uint8_t* temp_u = row;
8055   uint8_t* temp_v = row + row_size;
8056   if (!row)
8057     return 1;
8058 
8059   for (y = 0; y < height; ++y) {
8060     ScaleRowUp2_Linear(src_u, temp_u, width);
8061     ScaleRowUp2_Linear(src_v, temp_v, width);
8062     I444ToRGB24Row(src_y, temp_u, temp_v, dst_rgb24, yuvconstants, width);
8063     dst_rgb24 += dst_stride_rgb24;
8064     src_y += src_stride_y;
8065     src_u += src_stride_u;
8066     src_v += src_stride_v;
8067   }
8068 
8069   free_aligned_buffer_64(row);
8070   return 0;
8071 }
8072 
8073 LIBYUV_API
I422ToRGB24MatrixFilter(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgb24,int dst_stride_rgb24,const struct YuvConstants * yuvconstants,int width,int height,enum FilterMode filter)8074 int I422ToRGB24MatrixFilter(const uint8_t* src_y,
8075                             int src_stride_y,
8076                             const uint8_t* src_u,
8077                             int src_stride_u,
8078                             const uint8_t* src_v,
8079                             int src_stride_v,
8080                             uint8_t* dst_rgb24,
8081                             int dst_stride_rgb24,
8082                             const struct YuvConstants* yuvconstants,
8083                             int width,
8084                             int height,
8085                             enum FilterMode filter) {
8086   switch (filter) {
8087     case kFilterNone:
8088       return I422ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
8089                                src_stride_v, dst_rgb24, dst_stride_rgb24,
8090                                yuvconstants, width, height);
8091     case kFilterBilinear:
8092     case kFilterBox:
8093     case kFilterLinear:
8094       return I422ToRGB24MatrixLinear(
8095           src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
8096           dst_rgb24, dst_stride_rgb24, yuvconstants, width, height);
8097   }
8098 
8099   return -1;
8100 }
8101 
8102 LIBYUV_API
I420ToARGBMatrixFilter(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,enum FilterMode filter)8103 int I420ToARGBMatrixFilter(const uint8_t* src_y,
8104                            int src_stride_y,
8105                            const uint8_t* src_u,
8106                            int src_stride_u,
8107                            const uint8_t* src_v,
8108                            int src_stride_v,
8109                            uint8_t* dst_argb,
8110                            int dst_stride_argb,
8111                            const struct YuvConstants* yuvconstants,
8112                            int width,
8113                            int height,
8114                            enum FilterMode filter) {
8115   switch (filter) {
8116     case kFilterNone:
8117       return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
8118                               src_stride_v, dst_argb, dst_stride_argb,
8119                               yuvconstants, width, height);
8120     case kFilterBilinear:
8121     case kFilterBox:
8122       return I420ToARGBMatrixBilinear(
8123           src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
8124           dst_argb, dst_stride_argb, yuvconstants, width, height);
8125     case kFilterLinear:
8126       // Actually we can do this, but probably there's no usage.
8127       return -1;
8128   }
8129 
8130   return -1;
8131 }
8132 
8133 LIBYUV_API
I422ToARGBMatrixFilter(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,enum FilterMode filter)8134 int I422ToARGBMatrixFilter(const uint8_t* src_y,
8135                            int src_stride_y,
8136                            const uint8_t* src_u,
8137                            int src_stride_u,
8138                            const uint8_t* src_v,
8139                            int src_stride_v,
8140                            uint8_t* dst_argb,
8141                            int dst_stride_argb,
8142                            const struct YuvConstants* yuvconstants,
8143                            int width,
8144                            int height,
8145                            enum FilterMode filter) {
8146   switch (filter) {
8147     case kFilterNone:
8148       return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
8149                               src_stride_v, dst_argb, dst_stride_argb,
8150                               yuvconstants, width, height);
8151     case kFilterBilinear:
8152     case kFilterBox:
8153     case kFilterLinear:
8154       return I422ToARGBMatrixLinear(
8155           src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
8156           dst_argb, dst_stride_argb, yuvconstants, width, height);
8157   }
8158 
8159   return -1;
8160 }
8161 
8162 LIBYUV_API
I420ToRGB24MatrixFilter(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,uint8_t * dst_rgb24,int dst_stride_rgb24,const struct YuvConstants * yuvconstants,int width,int height,enum FilterMode filter)8163 int I420ToRGB24MatrixFilter(const uint8_t* src_y,
8164                             int src_stride_y,
8165                             const uint8_t* src_u,
8166                             int src_stride_u,
8167                             const uint8_t* src_v,
8168                             int src_stride_v,
8169                             uint8_t* dst_rgb24,
8170                             int dst_stride_rgb24,
8171                             const struct YuvConstants* yuvconstants,
8172                             int width,
8173                             int height,
8174                             enum FilterMode filter) {
8175   switch (filter) {
8176     case kFilterNone:
8177       return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
8178                                src_stride_v, dst_rgb24, dst_stride_rgb24,
8179                                yuvconstants, width, height);
8180     case kFilterLinear:  // TODO(fb): Implement Linear using Bilinear stride 0
8181     case kFilterBilinear:
8182     case kFilterBox:
8183       return I420ToRGB24MatrixBilinear(
8184           src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
8185           dst_rgb24, dst_stride_rgb24, yuvconstants, width, height);
8186   }
8187 
8188   return -1;
8189 }
8190 
8191 LIBYUV_API
I010ToAR30MatrixFilter(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height,enum FilterMode filter)8192 int I010ToAR30MatrixFilter(const uint16_t* src_y,
8193                            int src_stride_y,
8194                            const uint16_t* src_u,
8195                            int src_stride_u,
8196                            const uint16_t* src_v,
8197                            int src_stride_v,
8198                            uint8_t* dst_ar30,
8199                            int dst_stride_ar30,
8200                            const struct YuvConstants* yuvconstants,
8201                            int width,
8202                            int height,
8203                            enum FilterMode filter) {
8204   switch (filter) {
8205     case kFilterNone:
8206       return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
8207                               src_stride_v, dst_ar30, dst_stride_ar30,
8208                               yuvconstants, width, height);
8209     case kFilterLinear:  // TODO(fb): Implement Linear using Bilinear stride 0
8210     case kFilterBilinear:
8211     case kFilterBox:
8212       return I010ToAR30MatrixBilinear(
8213           src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
8214           dst_ar30, dst_stride_ar30, yuvconstants, width, height);
8215   }
8216 
8217   return -1;
8218 }
8219 
8220 LIBYUV_API
I210ToAR30MatrixFilter(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height,enum FilterMode filter)8221 int I210ToAR30MatrixFilter(const uint16_t* src_y,
8222                            int src_stride_y,
8223                            const uint16_t* src_u,
8224                            int src_stride_u,
8225                            const uint16_t* src_v,
8226                            int src_stride_v,
8227                            uint8_t* dst_ar30,
8228                            int dst_stride_ar30,
8229                            const struct YuvConstants* yuvconstants,
8230                            int width,
8231                            int height,
8232                            enum FilterMode filter) {
8233   switch (filter) {
8234     case kFilterNone:
8235       return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
8236                               src_stride_v, dst_ar30, dst_stride_ar30,
8237                               yuvconstants, width, height);
8238     case kFilterBilinear:
8239     case kFilterBox:
8240     case kFilterLinear:
8241       return I210ToAR30MatrixLinear(
8242           src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
8243           dst_ar30, dst_stride_ar30, yuvconstants, width, height);
8244   }
8245 
8246   return -1;
8247 }
8248 
8249 LIBYUV_API
I010ToARGBMatrixFilter(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,enum FilterMode filter)8250 int I010ToARGBMatrixFilter(const uint16_t* src_y,
8251                            int src_stride_y,
8252                            const uint16_t* src_u,
8253                            int src_stride_u,
8254                            const uint16_t* src_v,
8255                            int src_stride_v,
8256                            uint8_t* dst_argb,
8257                            int dst_stride_argb,
8258                            const struct YuvConstants* yuvconstants,
8259                            int width,
8260                            int height,
8261                            enum FilterMode filter) {
8262   switch (filter) {
8263     case kFilterNone:
8264       return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
8265                               src_stride_v, dst_argb, dst_stride_argb,
8266                               yuvconstants, width, height);
8267     case kFilterLinear:  // TODO(fb): Implement Linear using Bilinear stride 0
8268     case kFilterBilinear:
8269     case kFilterBox:
8270       return I010ToARGBMatrixBilinear(
8271           src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
8272           dst_argb, dst_stride_argb, yuvconstants, width, height);
8273   }
8274 
8275   return -1;
8276 }
8277 
8278 LIBYUV_API
I210ToARGBMatrixFilter(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,enum FilterMode filter)8279 int I210ToARGBMatrixFilter(const uint16_t* src_y,
8280                            int src_stride_y,
8281                            const uint16_t* src_u,
8282                            int src_stride_u,
8283                            const uint16_t* src_v,
8284                            int src_stride_v,
8285                            uint8_t* dst_argb,
8286                            int dst_stride_argb,
8287                            const struct YuvConstants* yuvconstants,
8288                            int width,
8289                            int height,
8290                            enum FilterMode filter) {
8291   switch (filter) {
8292     case kFilterNone:
8293       return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
8294                               src_stride_v, dst_argb, dst_stride_argb,
8295                               yuvconstants, width, height);
8296     case kFilterBilinear:
8297     case kFilterBox:
8298     case kFilterLinear:
8299       return I210ToARGBMatrixLinear(
8300           src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
8301           dst_argb, dst_stride_argb, yuvconstants, width, height);
8302   }
8303 
8304   return -1;
8305 }
8306 
8307 LIBYUV_API
I420AlphaToARGBMatrixFilter(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,const uint8_t * src_a,int src_stride_a,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,int attenuate,enum FilterMode filter)8308 int I420AlphaToARGBMatrixFilter(const uint8_t* src_y,
8309                                 int src_stride_y,
8310                                 const uint8_t* src_u,
8311                                 int src_stride_u,
8312                                 const uint8_t* src_v,
8313                                 int src_stride_v,
8314                                 const uint8_t* src_a,
8315                                 int src_stride_a,
8316                                 uint8_t* dst_argb,
8317                                 int dst_stride_argb,
8318                                 const struct YuvConstants* yuvconstants,
8319                                 int width,
8320                                 int height,
8321                                 int attenuate,
8322                                 enum FilterMode filter) {
8323   switch (filter) {
8324     case kFilterNone:
8325       return I420AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u,
8326                                    src_v, src_stride_v, src_a, src_stride_a,
8327                                    dst_argb, dst_stride_argb, yuvconstants,
8328                                    width, height, attenuate);
8329     case kFilterLinear:  // TODO(fb): Implement Linear using Bilinear stride 0
8330     case kFilterBilinear:
8331     case kFilterBox:
8332       return I420AlphaToARGBMatrixBilinear(
8333           src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, src_a,
8334           src_stride_a, dst_argb, dst_stride_argb, yuvconstants, width, height,
8335           attenuate);
8336   }
8337 
8338   return -1;
8339 }
8340 
8341 LIBYUV_API
I422AlphaToARGBMatrixFilter(const uint8_t * src_y,int src_stride_y,const uint8_t * src_u,int src_stride_u,const uint8_t * src_v,int src_stride_v,const uint8_t * src_a,int src_stride_a,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,int attenuate,enum FilterMode filter)8342 int I422AlphaToARGBMatrixFilter(const uint8_t* src_y,
8343                                 int src_stride_y,
8344                                 const uint8_t* src_u,
8345                                 int src_stride_u,
8346                                 const uint8_t* src_v,
8347                                 int src_stride_v,
8348                                 const uint8_t* src_a,
8349                                 int src_stride_a,
8350                                 uint8_t* dst_argb,
8351                                 int dst_stride_argb,
8352                                 const struct YuvConstants* yuvconstants,
8353                                 int width,
8354                                 int height,
8355                                 int attenuate,
8356                                 enum FilterMode filter) {
8357   switch (filter) {
8358     case kFilterNone:
8359       return I422AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u,
8360                                    src_v, src_stride_v, src_a, src_stride_a,
8361                                    dst_argb, dst_stride_argb, yuvconstants,
8362                                    width, height, attenuate);
8363     case kFilterBilinear:
8364     case kFilterBox:
8365     case kFilterLinear:
8366       return I422AlphaToARGBMatrixLinear(
8367           src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, src_a,
8368           src_stride_a, dst_argb, dst_stride_argb, yuvconstants, width, height,
8369           attenuate);
8370   }
8371 
8372   return -1;
8373 }
8374 
8375 LIBYUV_API
I010AlphaToARGBMatrixFilter(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,const uint16_t * src_a,int src_stride_a,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,int attenuate,enum FilterMode filter)8376 int I010AlphaToARGBMatrixFilter(const uint16_t* src_y,
8377                                 int src_stride_y,
8378                                 const uint16_t* src_u,
8379                                 int src_stride_u,
8380                                 const uint16_t* src_v,
8381                                 int src_stride_v,
8382                                 const uint16_t* src_a,
8383                                 int src_stride_a,
8384                                 uint8_t* dst_argb,
8385                                 int dst_stride_argb,
8386                                 const struct YuvConstants* yuvconstants,
8387                                 int width,
8388                                 int height,
8389                                 int attenuate,
8390                                 enum FilterMode filter) {
8391   switch (filter) {
8392     case kFilterNone:
8393       return I010AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u,
8394                                    src_v, src_stride_v, src_a, src_stride_a,
8395                                    dst_argb, dst_stride_argb, yuvconstants,
8396                                    width, height, attenuate);
8397     case kFilterLinear:  // TODO(fb): Implement Linear using Bilinear stride 0
8398     case kFilterBilinear:
8399     case kFilterBox:
8400       return I010AlphaToARGBMatrixBilinear(
8401           src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, src_a,
8402           src_stride_a, dst_argb, dst_stride_argb, yuvconstants, width, height,
8403           attenuate);
8404   }
8405 
8406   return -1;
8407 }
8408 
8409 LIBYUV_API
I210AlphaToARGBMatrixFilter(const uint16_t * src_y,int src_stride_y,const uint16_t * src_u,int src_stride_u,const uint16_t * src_v,int src_stride_v,const uint16_t * src_a,int src_stride_a,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,int attenuate,enum FilterMode filter)8410 int I210AlphaToARGBMatrixFilter(const uint16_t* src_y,
8411                                 int src_stride_y,
8412                                 const uint16_t* src_u,
8413                                 int src_stride_u,
8414                                 const uint16_t* src_v,
8415                                 int src_stride_v,
8416                                 const uint16_t* src_a,
8417                                 int src_stride_a,
8418                                 uint8_t* dst_argb,
8419                                 int dst_stride_argb,
8420                                 const struct YuvConstants* yuvconstants,
8421                                 int width,
8422                                 int height,
8423                                 int attenuate,
8424                                 enum FilterMode filter) {
8425   switch (filter) {
8426     case kFilterNone:
8427       return I210AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u,
8428                                    src_v, src_stride_v, src_a, src_stride_a,
8429                                    dst_argb, dst_stride_argb, yuvconstants,
8430                                    width, height, attenuate);
8431     case kFilterBilinear:
8432     case kFilterBox:
8433     case kFilterLinear:
8434       return I210AlphaToARGBMatrixLinear(
8435           src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v, src_a,
8436           src_stride_a, dst_argb, dst_stride_argb, yuvconstants, width, height,
8437           attenuate);
8438   }
8439 
8440   return -1;
8441 }
8442 
8443 // TODO(fb): Verify this function works correctly.  P010 is like NV12 but 10 bit
8444 // UV is biplanar.
8445 LIBYUV_API
P010ToARGBMatrixFilter(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,enum FilterMode filter)8446 int P010ToARGBMatrixFilter(const uint16_t* src_y,
8447                            int src_stride_y,
8448                            const uint16_t* src_uv,
8449                            int src_stride_uv,
8450                            uint8_t* dst_argb,
8451                            int dst_stride_argb,
8452                            const struct YuvConstants* yuvconstants,
8453                            int width,
8454                            int height,
8455                            enum FilterMode filter) {
8456   switch (filter) {
8457     case kFilterNone:
8458       return P010ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv,
8459                               dst_argb, dst_stride_argb, yuvconstants, width,
8460                               height);
8461     case kFilterLinear:  // TODO(fb): Implement Linear using Bilinear stride 0
8462     case kFilterBilinear:
8463     case kFilterBox:
8464       return P010ToARGBMatrixBilinear(src_y, src_stride_y, src_uv,
8465                                       src_stride_uv, dst_argb, dst_stride_argb,
8466                                       yuvconstants, width, height);
8467   }
8468 
8469   return -1;
8470 }
8471 
8472 LIBYUV_API
P210ToARGBMatrixFilter(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_argb,int dst_stride_argb,const struct YuvConstants * yuvconstants,int width,int height,enum FilterMode filter)8473 int P210ToARGBMatrixFilter(const uint16_t* src_y,
8474                            int src_stride_y,
8475                            const uint16_t* src_uv,
8476                            int src_stride_uv,
8477                            uint8_t* dst_argb,
8478                            int dst_stride_argb,
8479                            const struct YuvConstants* yuvconstants,
8480                            int width,
8481                            int height,
8482                            enum FilterMode filter) {
8483   switch (filter) {
8484     case kFilterNone:
8485       return P210ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv,
8486                               dst_argb, dst_stride_argb, yuvconstants, width,
8487                               height);
8488     case kFilterBilinear:
8489     case kFilterBox:
8490     case kFilterLinear:
8491       return P210ToARGBMatrixLinear(src_y, src_stride_y, src_uv, src_stride_uv,
8492                                     dst_argb, dst_stride_argb, yuvconstants,
8493                                     width, height);
8494   }
8495 
8496   return -1;
8497 }
8498 
8499 LIBYUV_API
P010ToAR30MatrixFilter(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height,enum FilterMode filter)8500 int P010ToAR30MatrixFilter(const uint16_t* src_y,
8501                            int src_stride_y,
8502                            const uint16_t* src_uv,
8503                            int src_stride_uv,
8504                            uint8_t* dst_ar30,
8505                            int dst_stride_ar30,
8506                            const struct YuvConstants* yuvconstants,
8507                            int width,
8508                            int height,
8509                            enum FilterMode filter) {
8510   switch (filter) {
8511     case kFilterNone:
8512       return P010ToAR30Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
8513                               dst_ar30, dst_stride_ar30, yuvconstants, width,
8514                               height);
8515     case kFilterLinear:  // TODO(fb): Implement Linear using Bilinear stride 0
8516     case kFilterBilinear:
8517     case kFilterBox:
8518       return P010ToAR30MatrixBilinear(src_y, src_stride_y, src_uv,
8519                                       src_stride_uv, dst_ar30, dst_stride_ar30,
8520                                       yuvconstants, width, height);
8521   }
8522 
8523   return -1;
8524 }
8525 
8526 LIBYUV_API
P210ToAR30MatrixFilter(const uint16_t * src_y,int src_stride_y,const uint16_t * src_uv,int src_stride_uv,uint8_t * dst_ar30,int dst_stride_ar30,const struct YuvConstants * yuvconstants,int width,int height,enum FilterMode filter)8527 int P210ToAR30MatrixFilter(const uint16_t* src_y,
8528                            int src_stride_y,
8529                            const uint16_t* src_uv,
8530                            int src_stride_uv,
8531                            uint8_t* dst_ar30,
8532                            int dst_stride_ar30,
8533                            const struct YuvConstants* yuvconstants,
8534                            int width,
8535                            int height,
8536                            enum FilterMode filter) {
8537   switch (filter) {
8538     case kFilterNone:
8539       return P210ToAR30Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
8540                               dst_ar30, dst_stride_ar30, yuvconstants, width,
8541                               height);
8542     case kFilterBilinear:
8543     case kFilterBox:
8544     case kFilterLinear:
8545       return P210ToAR30MatrixLinear(src_y, src_stride_y, src_uv, src_stride_uv,
8546                                     dst_ar30, dst_stride_ar30, yuvconstants,
8547                                     width, height);
8548   }
8549 
8550   return -1;
8551 }
8552 
8553 #ifdef __cplusplus
8554 }  // extern "C"
8555 }  // namespace libyuv
8556 #endif
8557