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