1 /*
2  *  Copyright 2011 The LibYuv Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS. All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "libyuv/convert_argb.h"
12 
13 #include "libyuv/cpu_id.h"
14 #ifdef HAVE_JPEG
15 #include "libyuv/mjpeg_decoder.h"
16 #endif
17 #include "libyuv/planar_functions.h"  // For CopyPlane and ARGBShuffle.
18 #include "libyuv/rotate_argb.h"
19 #include "libyuv/row.h"
20 #include "libyuv/video_common.h"
21 
22 #ifdef __cplusplus
23 namespace libyuv {
24 extern "C" {
25 #endif
26 
27 // Copy ARGB with optional flipping
28 LIBYUV_API
ARGBCopy(const uint8_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_NEON)
94   if (TestCpuFlag(kCpuHasNEON)) {
95     I422ToARGBRow = I422ToARGBRow_Any_NEON;
96     if (IS_ALIGNED(width, 8)) {
97       I422ToARGBRow = I422ToARGBRow_NEON;
98     }
99   }
100 #endif
101 #if defined(HAS_I422TOARGBROW_MMI)
102   if (TestCpuFlag(kCpuHasMMI)) {
103     I422ToARGBRow = I422ToARGBRow_Any_MMI;
104     if (IS_ALIGNED(width, 4)) {
105       I422ToARGBRow = I422ToARGBRow_MMI;
106     }
107   }
108 #endif
109 #if defined(HAS_I422TOARGBROW_MSA)
110   if (TestCpuFlag(kCpuHasMSA)) {
111     I422ToARGBRow = I422ToARGBRow_Any_MSA;
112     if (IS_ALIGNED(width, 8)) {
113       I422ToARGBRow = I422ToARGBRow_MSA;
114     }
115   }
116 #endif
117 
118   for (y = 0; y < height; ++y) {
119     I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
120     dst_argb += dst_stride_argb;
121     src_y += src_stride_y;
122     if (y & 1) {
123       src_u += src_stride_u;
124       src_v += src_stride_v;
125     }
126   }
127   return 0;
128 }
129 
130 // Convert I420 to ARGB.
131 LIBYUV_API
I420ToARGB(const uint8_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)132 int I420ToARGB(const uint8_t* src_y,
133                int src_stride_y,
134                const uint8_t* src_u,
135                int src_stride_u,
136                const uint8_t* src_v,
137                int src_stride_v,
138                uint8_t* dst_argb,
139                int dst_stride_argb,
140                int width,
141                int height) {
142   return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
143                           src_stride_v, dst_argb, dst_stride_argb,
144                           &kYuvI601Constants, width, height);
145 }
146 
147 // Convert I420 to ABGR.
148 LIBYUV_API
I420ToABGR(const uint8_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)149 int I420ToABGR(const uint8_t* src_y,
150                int src_stride_y,
151                const uint8_t* src_u,
152                int src_stride_u,
153                const uint8_t* src_v,
154                int src_stride_v,
155                uint8_t* dst_abgr,
156                int dst_stride_abgr,
157                int width,
158                int height) {
159   return I420ToARGBMatrix(src_y, src_stride_y, src_v,
160                           src_stride_v,  // Swap U and V
161                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
162                           &kYvuI601Constants,  // Use Yvu matrix
163                           width, height);
164 }
165 
166 // Convert J420 to ARGB.
167 LIBYUV_API
J420ToARGB(const uint8_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)168 int J420ToARGB(const uint8_t* src_y,
169                int src_stride_y,
170                const uint8_t* src_u,
171                int src_stride_u,
172                const uint8_t* src_v,
173                int src_stride_v,
174                uint8_t* dst_argb,
175                int dst_stride_argb,
176                int width,
177                int height) {
178   return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
179                           src_stride_v, dst_argb, dst_stride_argb,
180                           &kYuvJPEGConstants, width, height);
181 }
182 
183 // Convert J420 to ABGR.
184 LIBYUV_API
J420ToABGR(const uint8_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)185 int J420ToABGR(const uint8_t* src_y,
186                int src_stride_y,
187                const uint8_t* src_u,
188                int src_stride_u,
189                const uint8_t* src_v,
190                int src_stride_v,
191                uint8_t* dst_abgr,
192                int dst_stride_abgr,
193                int width,
194                int height) {
195   return I420ToARGBMatrix(src_y, src_stride_y, src_v,
196                           src_stride_v,  // Swap U and V
197                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
198                           &kYvuJPEGConstants,  // Use Yvu matrix
199                           width, height);
200 }
201 
202 // Convert H420 to ARGB.
203 LIBYUV_API
H420ToARGB(const uint8_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)204 int H420ToARGB(const uint8_t* src_y,
205                int src_stride_y,
206                const uint8_t* src_u,
207                int src_stride_u,
208                const uint8_t* src_v,
209                int src_stride_v,
210                uint8_t* dst_argb,
211                int dst_stride_argb,
212                int width,
213                int height) {
214   return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
215                           src_stride_v, dst_argb, dst_stride_argb,
216                           &kYuvH709Constants, width, height);
217 }
218 
219 // Convert H420 to ABGR.
220 LIBYUV_API
H420ToABGR(const uint8_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)221 int H420ToABGR(const uint8_t* src_y,
222                int src_stride_y,
223                const uint8_t* src_u,
224                int src_stride_u,
225                const uint8_t* src_v,
226                int src_stride_v,
227                uint8_t* dst_abgr,
228                int dst_stride_abgr,
229                int width,
230                int height) {
231   return I420ToARGBMatrix(src_y, src_stride_y, src_v,
232                           src_stride_v,  // Swap U and V
233                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
234                           &kYvuH709Constants,  // Use Yvu matrix
235                           width, height);
236 }
237 
238 // Convert U420 to ARGB.
239 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)240 int U420ToARGB(const uint8_t* src_y,
241                int src_stride_y,
242                const uint8_t* src_u,
243                int src_stride_u,
244                const uint8_t* src_v,
245                int src_stride_v,
246                uint8_t* dst_argb,
247                int dst_stride_argb,
248                int width,
249                int height) {
250   return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
251                           src_stride_v, dst_argb, dst_stride_argb,
252                           &kYuv2020Constants, width, height);
253 }
254 
255 // Convert U420 to ABGR.
256 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)257 int U420ToABGR(const uint8_t* src_y,
258                int src_stride_y,
259                const uint8_t* src_u,
260                int src_stride_u,
261                const uint8_t* src_v,
262                int src_stride_v,
263                uint8_t* dst_abgr,
264                int dst_stride_abgr,
265                int width,
266                int height) {
267   return I420ToARGBMatrix(src_y, src_stride_y, src_v,
268                           src_stride_v,  // Swap U and V
269                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
270                           &kYvu2020Constants,  // Use Yvu matrix
271                           width, height);
272 }
273 
274 // Convert I422 to ARGB with matrix.
275 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)276 int I422ToARGBMatrix(const uint8_t* src_y,
277                      int src_stride_y,
278                      const uint8_t* src_u,
279                      int src_stride_u,
280                      const uint8_t* src_v,
281                      int src_stride_v,
282                      uint8_t* dst_argb,
283                      int dst_stride_argb,
284                      const struct YuvConstants* yuvconstants,
285                      int width,
286                      int height) {
287   int y;
288   void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
289                         const uint8_t* v_buf, uint8_t* rgb_buf,
290                         const struct YuvConstants* yuvconstants, int width) =
291       I422ToARGBRow_C;
292   if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
293     return -1;
294   }
295   // Negative height means invert the image.
296   if (height < 0) {
297     height = -height;
298     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
299     dst_stride_argb = -dst_stride_argb;
300   }
301   // Coalesce rows.
302   if (src_stride_y == width && src_stride_u * 2 == width &&
303       src_stride_v * 2 == width && dst_stride_argb == width * 4) {
304     width *= height;
305     height = 1;
306     src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
307   }
308 #if defined(HAS_I422TOARGBROW_SSSE3)
309   if (TestCpuFlag(kCpuHasSSSE3)) {
310     I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
311     if (IS_ALIGNED(width, 8)) {
312       I422ToARGBRow = I422ToARGBRow_SSSE3;
313     }
314   }
315 #endif
316 #if defined(HAS_I422TOARGBROW_AVX2)
317   if (TestCpuFlag(kCpuHasAVX2)) {
318     I422ToARGBRow = I422ToARGBRow_Any_AVX2;
319     if (IS_ALIGNED(width, 16)) {
320       I422ToARGBRow = I422ToARGBRow_AVX2;
321     }
322   }
323 #endif
324 #if defined(HAS_I422TOARGBROW_NEON)
325   if (TestCpuFlag(kCpuHasNEON)) {
326     I422ToARGBRow = I422ToARGBRow_Any_NEON;
327     if (IS_ALIGNED(width, 8)) {
328       I422ToARGBRow = I422ToARGBRow_NEON;
329     }
330   }
331 #endif
332 #if defined(HAS_I422TOARGBROW_MMI)
333   if (TestCpuFlag(kCpuHasMMI)) {
334     I422ToARGBRow = I422ToARGBRow_Any_MMI;
335     if (IS_ALIGNED(width, 4)) {
336       I422ToARGBRow = I422ToARGBRow_MMI;
337     }
338   }
339 #endif
340 #if defined(HAS_I422TOARGBROW_MSA)
341   if (TestCpuFlag(kCpuHasMSA)) {
342     I422ToARGBRow = I422ToARGBRow_Any_MSA;
343     if (IS_ALIGNED(width, 8)) {
344       I422ToARGBRow = I422ToARGBRow_MSA;
345     }
346   }
347 #endif
348 
349   for (y = 0; y < height; ++y) {
350     I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
351     dst_argb += dst_stride_argb;
352     src_y += src_stride_y;
353     src_u += src_stride_u;
354     src_v += src_stride_v;
355   }
356   return 0;
357 }
358 
359 // Convert I422 to ARGB.
360 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)361 int I422ToARGB(const uint8_t* src_y,
362                int src_stride_y,
363                const uint8_t* src_u,
364                int src_stride_u,
365                const uint8_t* src_v,
366                int src_stride_v,
367                uint8_t* dst_argb,
368                int dst_stride_argb,
369                int width,
370                int height) {
371   return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
372                           src_stride_v, dst_argb, dst_stride_argb,
373                           &kYuvI601Constants, width, height);
374 }
375 
376 // Convert I422 to ABGR.
377 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)378 int I422ToABGR(const uint8_t* src_y,
379                int src_stride_y,
380                const uint8_t* src_u,
381                int src_stride_u,
382                const uint8_t* src_v,
383                int src_stride_v,
384                uint8_t* dst_abgr,
385                int dst_stride_abgr,
386                int width,
387                int height) {
388   return I422ToARGBMatrix(src_y, src_stride_y, src_v,
389                           src_stride_v,  // Swap U and V
390                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
391                           &kYvuI601Constants,  // Use Yvu matrix
392                           width, height);
393 }
394 
395 // Convert J422 to ARGB.
396 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)397 int J422ToARGB(const uint8_t* src_y,
398                int src_stride_y,
399                const uint8_t* src_u,
400                int src_stride_u,
401                const uint8_t* src_v,
402                int src_stride_v,
403                uint8_t* dst_argb,
404                int dst_stride_argb,
405                int width,
406                int height) {
407   return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
408                           src_stride_v, dst_argb, dst_stride_argb,
409                           &kYuvJPEGConstants, width, height);
410 }
411 
412 // Convert J422 to ABGR.
413 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)414 int J422ToABGR(const uint8_t* src_y,
415                int src_stride_y,
416                const uint8_t* src_u,
417                int src_stride_u,
418                const uint8_t* src_v,
419                int src_stride_v,
420                uint8_t* dst_abgr,
421                int dst_stride_abgr,
422                int width,
423                int height) {
424   return I422ToARGBMatrix(src_y, src_stride_y, src_v,
425                           src_stride_v,  // Swap U and V
426                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
427                           &kYvuJPEGConstants,  // Use Yvu matrix
428                           width, height);
429 }
430 
431 // Convert H422 to ARGB.
432 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)433 int H422ToARGB(const uint8_t* src_y,
434                int src_stride_y,
435                const uint8_t* src_u,
436                int src_stride_u,
437                const uint8_t* src_v,
438                int src_stride_v,
439                uint8_t* dst_argb,
440                int dst_stride_argb,
441                int width,
442                int height) {
443   return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
444                           src_stride_v, dst_argb, dst_stride_argb,
445                           &kYuvH709Constants, width, height);
446 }
447 
448 // Convert H422 to ABGR.
449 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)450 int H422ToABGR(const uint8_t* src_y,
451                int src_stride_y,
452                const uint8_t* src_u,
453                int src_stride_u,
454                const uint8_t* src_v,
455                int src_stride_v,
456                uint8_t* dst_abgr,
457                int dst_stride_abgr,
458                int width,
459                int height) {
460   return I422ToARGBMatrix(src_y, src_stride_y, src_v,
461                           src_stride_v,  // Swap U and V
462                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
463                           &kYvuH709Constants,  // Use Yvu matrix
464                           width, height);
465 }
466 
467 // Convert U422 to ARGB.
468 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)469 int U422ToARGB(const uint8_t* src_y,
470                int src_stride_y,
471                const uint8_t* src_u,
472                int src_stride_u,
473                const uint8_t* src_v,
474                int src_stride_v,
475                uint8_t* dst_argb,
476                int dst_stride_argb,
477                int width,
478                int height) {
479   return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
480                           src_stride_v, dst_argb, dst_stride_argb,
481                           &kYuv2020Constants, width, height);
482 }
483 
484 // Convert U422 to ABGR.
485 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)486 int U422ToABGR(const uint8_t* src_y,
487                int src_stride_y,
488                const uint8_t* src_u,
489                int src_stride_u,
490                const uint8_t* src_v,
491                int src_stride_v,
492                uint8_t* dst_abgr,
493                int dst_stride_abgr,
494                int width,
495                int height) {
496   return I422ToARGBMatrix(src_y, src_stride_y, src_v,
497                           src_stride_v,  // Swap U and V
498                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
499                           &kYvu2020Constants,  // Use Yvu matrix
500                           width, height);
501 }
502 
503 // Convert I444 to ARGB with matrix.
504 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)505 int I444ToARGBMatrix(const uint8_t* src_y,
506                      int src_stride_y,
507                      const uint8_t* src_u,
508                      int src_stride_u,
509                      const uint8_t* src_v,
510                      int src_stride_v,
511                      uint8_t* dst_argb,
512                      int dst_stride_argb,
513                      const struct YuvConstants* yuvconstants,
514                      int width,
515                      int height) {
516   int y;
517   void (*I444ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
518                         const uint8_t* v_buf, uint8_t* rgb_buf,
519                         const struct YuvConstants* yuvconstants, int width) =
520       I444ToARGBRow_C;
521   if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
522     return -1;
523   }
524   // Negative height means invert the image.
525   if (height < 0) {
526     height = -height;
527     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
528     dst_stride_argb = -dst_stride_argb;
529   }
530   // Coalesce rows.
531   if (src_stride_y == width && src_stride_u == width && src_stride_v == width &&
532       dst_stride_argb == width * 4) {
533     width *= height;
534     height = 1;
535     src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
536   }
537 #if defined(HAS_I444TOARGBROW_SSSE3)
538   if (TestCpuFlag(kCpuHasSSSE3)) {
539     I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
540     if (IS_ALIGNED(width, 8)) {
541       I444ToARGBRow = I444ToARGBRow_SSSE3;
542     }
543   }
544 #endif
545 #if defined(HAS_I444TOARGBROW_AVX2)
546   if (TestCpuFlag(kCpuHasAVX2)) {
547     I444ToARGBRow = I444ToARGBRow_Any_AVX2;
548     if (IS_ALIGNED(width, 16)) {
549       I444ToARGBRow = I444ToARGBRow_AVX2;
550     }
551   }
552 #endif
553 #if defined(HAS_I444TOARGBROW_NEON)
554   if (TestCpuFlag(kCpuHasNEON)) {
555     I444ToARGBRow = I444ToARGBRow_Any_NEON;
556     if (IS_ALIGNED(width, 8)) {
557       I444ToARGBRow = I444ToARGBRow_NEON;
558     }
559   }
560 #endif
561 #if defined(HAS_I444TOARGBROW_MMI)
562   if (TestCpuFlag(kCpuHasMMI)) {
563     I444ToARGBRow = I444ToARGBRow_Any_MMI;
564     if (IS_ALIGNED(width, 4)) {
565       I444ToARGBRow = I444ToARGBRow_MMI;
566     }
567   }
568 #endif
569 #if defined(HAS_I444TOARGBROW_MSA)
570   if (TestCpuFlag(kCpuHasMSA)) {
571     I444ToARGBRow = I444ToARGBRow_Any_MSA;
572     if (IS_ALIGNED(width, 8)) {
573       I444ToARGBRow = I444ToARGBRow_MSA;
574     }
575   }
576 #endif
577 
578   for (y = 0; y < height; ++y) {
579     I444ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
580     dst_argb += dst_stride_argb;
581     src_y += src_stride_y;
582     src_u += src_stride_u;
583     src_v += src_stride_v;
584   }
585   return 0;
586 }
587 
588 // Convert I444 to ARGB.
589 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)590 int I444ToARGB(const uint8_t* src_y,
591                int src_stride_y,
592                const uint8_t* src_u,
593                int src_stride_u,
594                const uint8_t* src_v,
595                int src_stride_v,
596                uint8_t* dst_argb,
597                int dst_stride_argb,
598                int width,
599                int height) {
600   return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
601                           src_stride_v, dst_argb, dst_stride_argb,
602                           &kYuvI601Constants, width, height);
603 }
604 
605 // Convert I444 to ABGR.
606 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)607 int I444ToABGR(const uint8_t* src_y,
608                int src_stride_y,
609                const uint8_t* src_u,
610                int src_stride_u,
611                const uint8_t* src_v,
612                int src_stride_v,
613                uint8_t* dst_abgr,
614                int dst_stride_abgr,
615                int width,
616                int height) {
617   return I444ToARGBMatrix(src_y, src_stride_y, src_v,
618                           src_stride_v,  // Swap U and V
619                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
620                           &kYvuI601Constants,  // Use Yvu matrix
621                           width, height);
622 }
623 
624 // Convert J444 to ARGB.
625 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)626 int J444ToARGB(const uint8_t* src_y,
627                int src_stride_y,
628                const uint8_t* src_u,
629                int src_stride_u,
630                const uint8_t* src_v,
631                int src_stride_v,
632                uint8_t* dst_argb,
633                int dst_stride_argb,
634                int width,
635                int height) {
636   return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
637                           src_stride_v, dst_argb, dst_stride_argb,
638                           &kYuvJPEGConstants, width, height);
639 }
640 
641 // Convert J444 to ABGR.
642 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)643 int J444ToABGR(const uint8_t* src_y,
644                int src_stride_y,
645                const uint8_t* src_u,
646                int src_stride_u,
647                const uint8_t* src_v,
648                int src_stride_v,
649                uint8_t* dst_abgr,
650                int dst_stride_abgr,
651                int width,
652                int height) {
653   return I444ToARGBMatrix(src_y, src_stride_y, src_v,
654                           src_stride_v,  // Swap U and V
655                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
656                           &kYvuJPEGConstants,  // Use Yvu matrix
657                           width, height);
658 }
659 
660 // Convert H444 to ARGB.
661 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)662 int H444ToARGB(const uint8_t* src_y,
663                int src_stride_y,
664                const uint8_t* src_u,
665                int src_stride_u,
666                const uint8_t* src_v,
667                int src_stride_v,
668                uint8_t* dst_argb,
669                int dst_stride_argb,
670                int width,
671                int height) {
672   return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
673                           src_stride_v, dst_argb, dst_stride_argb,
674                           &kYuvH709Constants, width, height);
675 }
676 
677 // Convert H444 to ABGR.
678 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)679 int H444ToABGR(const uint8_t* src_y,
680                int src_stride_y,
681                const uint8_t* src_u,
682                int src_stride_u,
683                const uint8_t* src_v,
684                int src_stride_v,
685                uint8_t* dst_abgr,
686                int dst_stride_abgr,
687                int width,
688                int height) {
689   return I444ToARGBMatrix(src_y, src_stride_y, src_v,
690                           src_stride_v,  // Swap U and V
691                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
692                           &kYvuH709Constants,  // Use Yvu matrix
693                           width, height);
694 }
695 
696 // Convert U444 to ARGB.
697 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)698 int U444ToARGB(const uint8_t* src_y,
699                int src_stride_y,
700                const uint8_t* src_u,
701                int src_stride_u,
702                const uint8_t* src_v,
703                int src_stride_v,
704                uint8_t* dst_argb,
705                int dst_stride_argb,
706                int width,
707                int height) {
708   return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
709                           src_stride_v, dst_argb, dst_stride_argb,
710                           &kYuv2020Constants, width, height);
711 }
712 
713 // Convert U444 to ABGR.
714 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)715 int U444ToABGR(const uint8_t* src_y,
716                int src_stride_y,
717                const uint8_t* src_u,
718                int src_stride_u,
719                const uint8_t* src_v,
720                int src_stride_v,
721                uint8_t* dst_abgr,
722                int dst_stride_abgr,
723                int width,
724                int height) {
725   return I444ToARGBMatrix(src_y, src_stride_y, src_v,
726                           src_stride_v,  // Swap U and V
727                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
728                           &kYvu2020Constants,  // Use Yvu matrix
729                           width, height);
730 }
731 
732 // Convert 10 bit YUV to ARGB with matrix.
733 // TODO(fbarchard): Consider passing scale multiplier to I210ToARGB to
734 // multiply 10 bit yuv into high bits to allow any number of bits.
735 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)736 int I010ToAR30Matrix(const uint16_t* src_y,
737                      int src_stride_y,
738                      const uint16_t* src_u,
739                      int src_stride_u,
740                      const uint16_t* src_v,
741                      int src_stride_v,
742                      uint8_t* dst_ar30,
743                      int dst_stride_ar30,
744                      const struct YuvConstants* yuvconstants,
745                      int width,
746                      int height) {
747   int y;
748   void (*I210ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
749                         const uint16_t* v_buf, uint8_t* rgb_buf,
750                         const struct YuvConstants* yuvconstants, int width) =
751       I210ToAR30Row_C;
752   if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
753     return -1;
754   }
755   // Negative height means invert the image.
756   if (height < 0) {
757     height = -height;
758     dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
759     dst_stride_ar30 = -dst_stride_ar30;
760   }
761 #if defined(HAS_I210TOAR30ROW_SSSE3)
762   if (TestCpuFlag(kCpuHasSSSE3)) {
763     I210ToAR30Row = I210ToAR30Row_Any_SSSE3;
764     if (IS_ALIGNED(width, 8)) {
765       I210ToAR30Row = I210ToAR30Row_SSSE3;
766     }
767   }
768 #endif
769 #if defined(HAS_I210TOAR30ROW_AVX2)
770   if (TestCpuFlag(kCpuHasAVX2)) {
771     I210ToAR30Row = I210ToAR30Row_Any_AVX2;
772     if (IS_ALIGNED(width, 16)) {
773       I210ToAR30Row = I210ToAR30Row_AVX2;
774     }
775   }
776 #endif
777   for (y = 0; y < height; ++y) {
778     I210ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
779     dst_ar30 += dst_stride_ar30;
780     src_y += src_stride_y;
781     if (y & 1) {
782       src_u += src_stride_u;
783       src_v += src_stride_v;
784     }
785   }
786   return 0;
787 }
788 
789 // Convert I010 to AR30.
790 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)791 int I010ToAR30(const uint16_t* src_y,
792                int src_stride_y,
793                const uint16_t* src_u,
794                int src_stride_u,
795                const uint16_t* src_v,
796                int src_stride_v,
797                uint8_t* dst_ar30,
798                int dst_stride_ar30,
799                int width,
800                int height) {
801   return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
802                           src_stride_v, dst_ar30, dst_stride_ar30,
803                           &kYuvI601Constants, width, height);
804 }
805 
806 // Convert H010 to AR30.
807 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)808 int H010ToAR30(const uint16_t* src_y,
809                int src_stride_y,
810                const uint16_t* src_u,
811                int src_stride_u,
812                const uint16_t* src_v,
813                int src_stride_v,
814                uint8_t* dst_ar30,
815                int dst_stride_ar30,
816                int width,
817                int height) {
818   return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
819                           src_stride_v, dst_ar30, dst_stride_ar30,
820                           &kYuvH709Constants, width, height);
821 }
822 
823 // Convert U010 to AR30.
824 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)825 int U010ToAR30(const uint16_t* src_y,
826                int src_stride_y,
827                const uint16_t* src_u,
828                int src_stride_u,
829                const uint16_t* src_v,
830                int src_stride_v,
831                uint8_t* dst_ar30,
832                int dst_stride_ar30,
833                int width,
834                int height) {
835   return I010ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
836                           src_stride_v, dst_ar30, dst_stride_ar30,
837                           &kYuv2020Constants, width, height);
838 }
839 
840 // Convert I010 to AB30.
841 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)842 int I010ToAB30(const uint16_t* src_y,
843                int src_stride_y,
844                const uint16_t* src_u,
845                int src_stride_u,
846                const uint16_t* src_v,
847                int src_stride_v,
848                uint8_t* dst_ab30,
849                int dst_stride_ab30,
850                int width,
851                int height) {
852   return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
853                           src_stride_u, dst_ab30, dst_stride_ab30,
854                           &kYvuI601Constants, width, height);
855 }
856 
857 // Convert H010 to AB30.
858 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)859 int H010ToAB30(const uint16_t* src_y,
860                int src_stride_y,
861                const uint16_t* src_u,
862                int src_stride_u,
863                const uint16_t* src_v,
864                int src_stride_v,
865                uint8_t* dst_ab30,
866                int dst_stride_ab30,
867                int width,
868                int height) {
869   return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
870                           src_stride_u, dst_ab30, dst_stride_ab30,
871                           &kYvuH709Constants, width, height);
872 }
873 
874 // Convert U010 to AB30.
875 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)876 int U010ToAB30(const uint16_t* src_y,
877                int src_stride_y,
878                const uint16_t* src_u,
879                int src_stride_u,
880                const uint16_t* src_v,
881                int src_stride_v,
882                uint8_t* dst_ab30,
883                int dst_stride_ab30,
884                int width,
885                int height) {
886   return I010ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
887                           src_stride_u, dst_ab30, dst_stride_ab30,
888                           &kYuv2020Constants, width, height);
889 }
890 
891 // Convert 10 bit YUV to ARGB with matrix.
892 // TODO(fbarchard): Consider passing scale multiplier to I210ToARGB to
893 // multiply 10 bit yuv into high bits to allow any number of bits.
894 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)895 int I210ToAR30Matrix(const uint16_t* src_y,
896                      int src_stride_y,
897                      const uint16_t* src_u,
898                      int src_stride_u,
899                      const uint16_t* src_v,
900                      int src_stride_v,
901                      uint8_t* dst_ar30,
902                      int dst_stride_ar30,
903                      const struct YuvConstants* yuvconstants,
904                      int width,
905                      int height) {
906   int y;
907   void (*I210ToAR30Row)(const uint16_t* y_buf, const uint16_t* u_buf,
908                         const uint16_t* v_buf, uint8_t* rgb_buf,
909                         const struct YuvConstants* yuvconstants, int width) =
910       I210ToAR30Row_C;
911   if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
912     return -1;
913   }
914   // Negative height means invert the image.
915   if (height < 0) {
916     height = -height;
917     dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
918     dst_stride_ar30 = -dst_stride_ar30;
919   }
920 #if defined(HAS_I210TOAR30ROW_SSSE3)
921   if (TestCpuFlag(kCpuHasSSSE3)) {
922     I210ToAR30Row = I210ToAR30Row_Any_SSSE3;
923     if (IS_ALIGNED(width, 8)) {
924       I210ToAR30Row = I210ToAR30Row_SSSE3;
925     }
926   }
927 #endif
928 #if defined(HAS_I210TOAR30ROW_AVX2)
929   if (TestCpuFlag(kCpuHasAVX2)) {
930     I210ToAR30Row = I210ToAR30Row_Any_AVX2;
931     if (IS_ALIGNED(width, 16)) {
932       I210ToAR30Row = I210ToAR30Row_AVX2;
933     }
934   }
935 #endif
936   for (y = 0; y < height; ++y) {
937     I210ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
938     dst_ar30 += dst_stride_ar30;
939     src_y += src_stride_y;
940     src_u += src_stride_u;
941     src_v += src_stride_v;
942   }
943   return 0;
944 }
945 
946 // Convert I210 to AR30.
947 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)948 int I210ToAR30(const uint16_t* src_y,
949                int src_stride_y,
950                const uint16_t* src_u,
951                int src_stride_u,
952                const uint16_t* src_v,
953                int src_stride_v,
954                uint8_t* dst_ar30,
955                int dst_stride_ar30,
956                int width,
957                int height) {
958   return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
959                           src_stride_v, dst_ar30, dst_stride_ar30,
960                           &kYuvI601Constants, width, height);
961 }
962 
963 // Convert H210 to AR30.
964 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)965 int H210ToAR30(const uint16_t* src_y,
966                int src_stride_y,
967                const uint16_t* src_u,
968                int src_stride_u,
969                const uint16_t* src_v,
970                int src_stride_v,
971                uint8_t* dst_ar30,
972                int dst_stride_ar30,
973                int width,
974                int height) {
975   return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
976                           src_stride_v, dst_ar30, dst_stride_ar30,
977                           &kYuvH709Constants, width, height);
978 }
979 
980 // Convert U210 to AR30.
981 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)982 int U210ToAR30(const uint16_t* src_y,
983                int src_stride_y,
984                const uint16_t* src_u,
985                int src_stride_u,
986                const uint16_t* src_v,
987                int src_stride_v,
988                uint8_t* dst_ar30,
989                int dst_stride_ar30,
990                int width,
991                int height) {
992   return I210ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
993                           src_stride_v, dst_ar30, dst_stride_ar30,
994                           &kYuv2020Constants, width, height);
995 }
996 
997 // Convert I210 to AB30.
998 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)999 int I210ToAB30(const uint16_t* src_y,
1000                int src_stride_y,
1001                const uint16_t* src_u,
1002                int src_stride_u,
1003                const uint16_t* src_v,
1004                int src_stride_v,
1005                uint8_t* dst_ab30,
1006                int dst_stride_ab30,
1007                int width,
1008                int height) {
1009   return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1010                           src_stride_u, dst_ab30, dst_stride_ab30,
1011                           &kYvuI601Constants, width, height);
1012 }
1013 
1014 // Convert H210 to AB30.
1015 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)1016 int H210ToAB30(const uint16_t* src_y,
1017                int src_stride_y,
1018                const uint16_t* src_u,
1019                int src_stride_u,
1020                const uint16_t* src_v,
1021                int src_stride_v,
1022                uint8_t* dst_ab30,
1023                int dst_stride_ab30,
1024                int width,
1025                int height) {
1026   return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1027                           src_stride_u, dst_ab30, dst_stride_ab30,
1028                           &kYvuH709Constants, width, height);
1029 }
1030 
1031 // Convert U210 to AB30.
1032 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)1033 int U210ToAB30(const uint16_t* src_y,
1034                int src_stride_y,
1035                const uint16_t* src_u,
1036                int src_stride_u,
1037                const uint16_t* src_v,
1038                int src_stride_v,
1039                uint8_t* dst_ab30,
1040                int dst_stride_ab30,
1041                int width,
1042                int height) {
1043   return I210ToAR30Matrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
1044                           src_stride_u, dst_ab30, dst_stride_ab30,
1045                           &kYuv2020Constants, width, height);
1046 }
1047 
1048 // Convert 10 bit YUV to ARGB with matrix.
1049 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)1050 int I010ToARGBMatrix(const uint16_t* src_y,
1051                      int src_stride_y,
1052                      const uint16_t* src_u,
1053                      int src_stride_u,
1054                      const uint16_t* src_v,
1055                      int src_stride_v,
1056                      uint8_t* dst_argb,
1057                      int dst_stride_argb,
1058                      const struct YuvConstants* yuvconstants,
1059                      int width,
1060                      int height) {
1061   int y;
1062   void (*I210ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
1063                         const uint16_t* v_buf, uint8_t* rgb_buf,
1064                         const struct YuvConstants* yuvconstants, int width) =
1065       I210ToARGBRow_C;
1066   if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
1067     return -1;
1068   }
1069   // Negative height means invert the image.
1070   if (height < 0) {
1071     height = -height;
1072     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1073     dst_stride_argb = -dst_stride_argb;
1074   }
1075 #if defined(HAS_I210TOARGBROW_SSSE3)
1076   if (TestCpuFlag(kCpuHasSSSE3)) {
1077     I210ToARGBRow = I210ToARGBRow_Any_SSSE3;
1078     if (IS_ALIGNED(width, 8)) {
1079       I210ToARGBRow = I210ToARGBRow_SSSE3;
1080     }
1081   }
1082 #endif
1083 #if defined(HAS_I210TOARGBROW_AVX2)
1084   if (TestCpuFlag(kCpuHasAVX2)) {
1085     I210ToARGBRow = I210ToARGBRow_Any_AVX2;
1086     if (IS_ALIGNED(width, 16)) {
1087       I210ToARGBRow = I210ToARGBRow_AVX2;
1088     }
1089   }
1090 #endif
1091 #if defined(HAS_I210TOARGBROW_MMI)
1092   if (TestCpuFlag(kCpuHasMMI)) {
1093     I210ToARGBRow = I210ToARGBRow_Any_MMI;
1094     if (IS_ALIGNED(width, 4)) {
1095       I210ToARGBRow = I210ToARGBRow_MMI;
1096     }
1097   }
1098 #endif
1099   for (y = 0; y < height; ++y) {
1100     I210ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
1101     dst_argb += dst_stride_argb;
1102     src_y += src_stride_y;
1103     if (y & 1) {
1104       src_u += src_stride_u;
1105       src_v += src_stride_v;
1106     }
1107   }
1108   return 0;
1109 }
1110 
1111 // Convert I010 to ARGB.
1112 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)1113 int I010ToARGB(const uint16_t* src_y,
1114                int src_stride_y,
1115                const uint16_t* src_u,
1116                int src_stride_u,
1117                const uint16_t* src_v,
1118                int src_stride_v,
1119                uint8_t* dst_argb,
1120                int dst_stride_argb,
1121                int width,
1122                int height) {
1123   return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1124                           src_stride_v, dst_argb, dst_stride_argb,
1125                           &kYuvI601Constants, width, height);
1126 }
1127 
1128 // Convert I010 to ABGR.
1129 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)1130 int I010ToABGR(const uint16_t* src_y,
1131                int src_stride_y,
1132                const uint16_t* src_u,
1133                int src_stride_u,
1134                const uint16_t* src_v,
1135                int src_stride_v,
1136                uint8_t* dst_abgr,
1137                int dst_stride_abgr,
1138                int width,
1139                int height) {
1140   return I010ToARGBMatrix(src_y, src_stride_y, src_v,
1141                           src_stride_v,  // Swap U and V
1142                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1143                           &kYvuI601Constants,  // Use Yvu matrix
1144                           width, height);
1145 }
1146 
1147 // Convert H010 to ARGB.
1148 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)1149 int H010ToARGB(const uint16_t* src_y,
1150                int src_stride_y,
1151                const uint16_t* src_u,
1152                int src_stride_u,
1153                const uint16_t* src_v,
1154                int src_stride_v,
1155                uint8_t* dst_argb,
1156                int dst_stride_argb,
1157                int width,
1158                int height) {
1159   return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1160                           src_stride_v, dst_argb, dst_stride_argb,
1161                           &kYuvH709Constants, width, height);
1162 }
1163 
1164 // Convert H010 to ABGR.
1165 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)1166 int H010ToABGR(const uint16_t* src_y,
1167                int src_stride_y,
1168                const uint16_t* src_u,
1169                int src_stride_u,
1170                const uint16_t* src_v,
1171                int src_stride_v,
1172                uint8_t* dst_abgr,
1173                int dst_stride_abgr,
1174                int width,
1175                int height) {
1176   return I010ToARGBMatrix(src_y, src_stride_y, src_v,
1177                           src_stride_v,  // Swap U and V
1178                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1179                           &kYvuH709Constants,  // Use Yvu matrix
1180                           width, height);
1181 }
1182 
1183 // Convert U010 to ARGB.
1184 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)1185 int U010ToARGB(const uint16_t* src_y,
1186                int src_stride_y,
1187                const uint16_t* src_u,
1188                int src_stride_u,
1189                const uint16_t* src_v,
1190                int src_stride_v,
1191                uint8_t* dst_argb,
1192                int dst_stride_argb,
1193                int width,
1194                int height) {
1195   return I010ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1196                           src_stride_v, dst_argb, dst_stride_argb,
1197                           &kYuv2020Constants, width, height);
1198 }
1199 
1200 // Convert U010 to ABGR.
1201 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)1202 int U010ToABGR(const uint16_t* src_y,
1203                int src_stride_y,
1204                const uint16_t* src_u,
1205                int src_stride_u,
1206                const uint16_t* src_v,
1207                int src_stride_v,
1208                uint8_t* dst_abgr,
1209                int dst_stride_abgr,
1210                int width,
1211                int height) {
1212   return I010ToARGBMatrix(src_y, src_stride_y, src_v,
1213                           src_stride_v,  // Swap U and V
1214                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1215                           &kYvu2020Constants,  // Use Yvu matrix
1216                           width, height);
1217 }
1218 
1219 // Convert 10 bit 422 YUV to ARGB with matrix.
1220 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)1221 int I210ToARGBMatrix(const uint16_t* src_y,
1222                      int src_stride_y,
1223                      const uint16_t* src_u,
1224                      int src_stride_u,
1225                      const uint16_t* src_v,
1226                      int src_stride_v,
1227                      uint8_t* dst_argb,
1228                      int dst_stride_argb,
1229                      const struct YuvConstants* yuvconstants,
1230                      int width,
1231                      int height) {
1232   int y;
1233   void (*I210ToARGBRow)(const uint16_t* y_buf, const uint16_t* u_buf,
1234                         const uint16_t* v_buf, uint8_t* rgb_buf,
1235                         const struct YuvConstants* yuvconstants, int width) =
1236       I210ToARGBRow_C;
1237   if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
1238     return -1;
1239   }
1240   // Negative height means invert the image.
1241   if (height < 0) {
1242     height = -height;
1243     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1244     dst_stride_argb = -dst_stride_argb;
1245   }
1246 #if defined(HAS_I210TOARGBROW_SSSE3)
1247   if (TestCpuFlag(kCpuHasSSSE3)) {
1248     I210ToARGBRow = I210ToARGBRow_Any_SSSE3;
1249     if (IS_ALIGNED(width, 8)) {
1250       I210ToARGBRow = I210ToARGBRow_SSSE3;
1251     }
1252   }
1253 #endif
1254 #if defined(HAS_I210TOARGBROW_AVX2)
1255   if (TestCpuFlag(kCpuHasAVX2)) {
1256     I210ToARGBRow = I210ToARGBRow_Any_AVX2;
1257     if (IS_ALIGNED(width, 16)) {
1258       I210ToARGBRow = I210ToARGBRow_AVX2;
1259     }
1260   }
1261 #endif
1262 #if defined(HAS_I210TOARGBROW_MMI)
1263   if (TestCpuFlag(kCpuHasMMI)) {
1264     I210ToARGBRow = I210ToARGBRow_Any_MMI;
1265     if (IS_ALIGNED(width, 4)) {
1266       I210ToARGBRow = I210ToARGBRow_MMI;
1267     }
1268   }
1269 #endif
1270   for (y = 0; y < height; ++y) {
1271     I210ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width);
1272     dst_argb += dst_stride_argb;
1273     src_y += src_stride_y;
1274     src_u += src_stride_u;
1275     src_v += src_stride_v;
1276   }
1277   return 0;
1278 }
1279 
1280 // Convert I210 to ARGB.
1281 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)1282 int I210ToARGB(const uint16_t* src_y,
1283                int src_stride_y,
1284                const uint16_t* src_u,
1285                int src_stride_u,
1286                const uint16_t* src_v,
1287                int src_stride_v,
1288                uint8_t* dst_argb,
1289                int dst_stride_argb,
1290                int width,
1291                int height) {
1292   return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1293                           src_stride_v, dst_argb, dst_stride_argb,
1294                           &kYuvI601Constants, width, height);
1295 }
1296 
1297 // Convert I210 to ABGR.
1298 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)1299 int I210ToABGR(const uint16_t* src_y,
1300                int src_stride_y,
1301                const uint16_t* src_u,
1302                int src_stride_u,
1303                const uint16_t* src_v,
1304                int src_stride_v,
1305                uint8_t* dst_abgr,
1306                int dst_stride_abgr,
1307                int width,
1308                int height) {
1309   return I210ToARGBMatrix(src_y, src_stride_y, src_v,
1310                           src_stride_v,  // Swap U and V
1311                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1312                           &kYvuI601Constants,  // Use Yvu matrix
1313                           width, height);
1314 }
1315 
1316 // Convert H210 to ARGB.
1317 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)1318 int H210ToARGB(const uint16_t* src_y,
1319                int src_stride_y,
1320                const uint16_t* src_u,
1321                int src_stride_u,
1322                const uint16_t* src_v,
1323                int src_stride_v,
1324                uint8_t* dst_argb,
1325                int dst_stride_argb,
1326                int width,
1327                int height) {
1328   return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1329                           src_stride_v, dst_argb, dst_stride_argb,
1330                           &kYuvH709Constants, width, height);
1331 }
1332 
1333 // Convert H210 to ABGR.
1334 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)1335 int H210ToABGR(const uint16_t* src_y,
1336                int src_stride_y,
1337                const uint16_t* src_u,
1338                int src_stride_u,
1339                const uint16_t* src_v,
1340                int src_stride_v,
1341                uint8_t* dst_abgr,
1342                int dst_stride_abgr,
1343                int width,
1344                int height) {
1345   return I210ToARGBMatrix(src_y, src_stride_y, src_v,
1346                           src_stride_v,  // Swap U and V
1347                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1348                           &kYvuH709Constants,  // Use Yvu matrix
1349                           width, height);
1350 }
1351 
1352 // Convert U210 to ARGB.
1353 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)1354 int U210ToARGB(const uint16_t* src_y,
1355                int src_stride_y,
1356                const uint16_t* src_u,
1357                int src_stride_u,
1358                const uint16_t* src_v,
1359                int src_stride_v,
1360                uint8_t* dst_argb,
1361                int dst_stride_argb,
1362                int width,
1363                int height) {
1364   return I210ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1365                           src_stride_v, dst_argb, dst_stride_argb,
1366                           &kYuv2020Constants, width, height);
1367 }
1368 
1369 // Convert U210 to ABGR.
1370 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)1371 int U210ToABGR(const uint16_t* src_y,
1372                int src_stride_y,
1373                const uint16_t* src_u,
1374                int src_stride_u,
1375                const uint16_t* src_v,
1376                int src_stride_v,
1377                uint8_t* dst_abgr,
1378                int dst_stride_abgr,
1379                int width,
1380                int height) {
1381   return I210ToARGBMatrix(src_y, src_stride_y, src_v,
1382                           src_stride_v,  // Swap U and V
1383                           src_u, src_stride_u, dst_abgr, dst_stride_abgr,
1384                           &kYvu2020Constants,  // Use Yvu matrix
1385                           width, height);
1386 }
1387 
1388 // Convert I420 with Alpha to preattenuated ARGB with matrix.
1389 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)1390 int I420AlphaToARGBMatrix(const uint8_t* src_y,
1391                           int src_stride_y,
1392                           const uint8_t* src_u,
1393                           int src_stride_u,
1394                           const uint8_t* src_v,
1395                           int src_stride_v,
1396                           const uint8_t* src_a,
1397                           int src_stride_a,
1398                           uint8_t* dst_argb,
1399                           int dst_stride_argb,
1400                           const struct YuvConstants* yuvconstants,
1401                           int width,
1402                           int height,
1403                           int attenuate) {
1404   int y;
1405   void (*I422AlphaToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
1406                              const uint8_t* v_buf, const uint8_t* a_buf,
1407                              uint8_t* dst_argb,
1408                              const struct YuvConstants* yuvconstants,
1409                              int width) = I422AlphaToARGBRow_C;
1410   void (*ARGBAttenuateRow)(const uint8_t* src_argb, uint8_t* dst_argb,
1411                            int width) = ARGBAttenuateRow_C;
1412   if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
1413     return -1;
1414   }
1415   // Negative height means invert the image.
1416   if (height < 0) {
1417     height = -height;
1418     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1419     dst_stride_argb = -dst_stride_argb;
1420   }
1421 #if defined(HAS_I422ALPHATOARGBROW_SSSE3)
1422   if (TestCpuFlag(kCpuHasSSSE3)) {
1423     I422AlphaToARGBRow = I422AlphaToARGBRow_Any_SSSE3;
1424     if (IS_ALIGNED(width, 8)) {
1425       I422AlphaToARGBRow = I422AlphaToARGBRow_SSSE3;
1426     }
1427   }
1428 #endif
1429 #if defined(HAS_I422ALPHATOARGBROW_AVX2)
1430   if (TestCpuFlag(kCpuHasAVX2)) {
1431     I422AlphaToARGBRow = I422AlphaToARGBRow_Any_AVX2;
1432     if (IS_ALIGNED(width, 16)) {
1433       I422AlphaToARGBRow = I422AlphaToARGBRow_AVX2;
1434     }
1435   }
1436 #endif
1437 #if defined(HAS_I422ALPHATOARGBROW_NEON)
1438   if (TestCpuFlag(kCpuHasNEON)) {
1439     I422AlphaToARGBRow = I422AlphaToARGBRow_Any_NEON;
1440     if (IS_ALIGNED(width, 8)) {
1441       I422AlphaToARGBRow = I422AlphaToARGBRow_NEON;
1442     }
1443   }
1444 #endif
1445 #if defined(HAS_I422ALPHATOARGBROW_MMI)
1446   if (TestCpuFlag(kCpuHasMMI)) {
1447     I422AlphaToARGBRow = I422AlphaToARGBRow_Any_MMI;
1448     if (IS_ALIGNED(width, 4)) {
1449       I422AlphaToARGBRow = I422AlphaToARGBRow_MMI;
1450     }
1451   }
1452 #endif
1453 #if defined(HAS_I422ALPHATOARGBROW_MSA)
1454   if (TestCpuFlag(kCpuHasMSA)) {
1455     I422AlphaToARGBRow = I422AlphaToARGBRow_Any_MSA;
1456     if (IS_ALIGNED(width, 8)) {
1457       I422AlphaToARGBRow = I422AlphaToARGBRow_MSA;
1458     }
1459   }
1460 #endif
1461 #if defined(HAS_ARGBATTENUATEROW_SSSE3)
1462   if (TestCpuFlag(kCpuHasSSSE3)) {
1463     ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3;
1464     if (IS_ALIGNED(width, 4)) {
1465       ARGBAttenuateRow = ARGBAttenuateRow_SSSE3;
1466     }
1467   }
1468 #endif
1469 #if defined(HAS_ARGBATTENUATEROW_AVX2)
1470   if (TestCpuFlag(kCpuHasAVX2)) {
1471     ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2;
1472     if (IS_ALIGNED(width, 8)) {
1473       ARGBAttenuateRow = ARGBAttenuateRow_AVX2;
1474     }
1475   }
1476 #endif
1477 #if defined(HAS_ARGBATTENUATEROW_NEON)
1478   if (TestCpuFlag(kCpuHasNEON)) {
1479     ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON;
1480     if (IS_ALIGNED(width, 8)) {
1481       ARGBAttenuateRow = ARGBAttenuateRow_NEON;
1482     }
1483   }
1484 #endif
1485 #if defined(HAS_ARGBATTENUATEROW_MMI)
1486   if (TestCpuFlag(kCpuHasMMI)) {
1487     ARGBAttenuateRow = ARGBAttenuateRow_Any_MMI;
1488     if (IS_ALIGNED(width, 2)) {
1489       ARGBAttenuateRow = ARGBAttenuateRow_MMI;
1490     }
1491   }
1492 #endif
1493 #if defined(HAS_ARGBATTENUATEROW_MSA)
1494   if (TestCpuFlag(kCpuHasMSA)) {
1495     ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA;
1496     if (IS_ALIGNED(width, 8)) {
1497       ARGBAttenuateRow = ARGBAttenuateRow_MSA;
1498     }
1499   }
1500 #endif
1501 
1502   for (y = 0; y < height; ++y) {
1503     I422AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants,
1504                        width);
1505     if (attenuate) {
1506       ARGBAttenuateRow(dst_argb, dst_argb, width);
1507     }
1508     dst_argb += dst_stride_argb;
1509     src_a += src_stride_a;
1510     src_y += src_stride_y;
1511     if (y & 1) {
1512       src_u += src_stride_u;
1513       src_v += src_stride_v;
1514     }
1515   }
1516   return 0;
1517 }
1518 
1519 // Convert I420 with Alpha to ARGB.
1520 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)1521 int I420AlphaToARGB(const uint8_t* src_y,
1522                     int src_stride_y,
1523                     const uint8_t* src_u,
1524                     int src_stride_u,
1525                     const uint8_t* src_v,
1526                     int src_stride_v,
1527                     const uint8_t* src_a,
1528                     int src_stride_a,
1529                     uint8_t* dst_argb,
1530                     int dst_stride_argb,
1531                     int width,
1532                     int height,
1533                     int attenuate) {
1534   return I420AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
1535                                src_stride_v, src_a, src_stride_a, dst_argb,
1536                                dst_stride_argb, &kYuvI601Constants, width,
1537                                height, attenuate);
1538 }
1539 
1540 // Convert I420 with Alpha to ABGR.
1541 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)1542 int I420AlphaToABGR(const uint8_t* src_y,
1543                     int src_stride_y,
1544                     const uint8_t* src_u,
1545                     int src_stride_u,
1546                     const uint8_t* src_v,
1547                     int src_stride_v,
1548                     const uint8_t* src_a,
1549                     int src_stride_a,
1550                     uint8_t* dst_abgr,
1551                     int dst_stride_abgr,
1552                     int width,
1553                     int height,
1554                     int attenuate) {
1555   return I420AlphaToARGBMatrix(
1556       src_y, src_stride_y, src_v, src_stride_v,  // Swap U and V
1557       src_u, src_stride_u, src_a, src_stride_a, dst_abgr, dst_stride_abgr,
1558       &kYvuI601Constants,  // Use Yvu matrix
1559       width, height, attenuate);
1560 }
1561 
1562 // Convert I400 to ARGB with matrix.
1563 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)1564 int I400ToARGBMatrix(const uint8_t* src_y,
1565                      int src_stride_y,
1566                      uint8_t* dst_argb,
1567                      int dst_stride_argb,
1568                      const struct YuvConstants* yuvconstants,
1569                      int width,
1570                      int height) {
1571   int y;
1572   void (*I400ToARGBRow)(const uint8_t* y_buf, uint8_t* rgb_buf,
1573                         const struct YuvConstants* yuvconstants, int width) =
1574       I400ToARGBRow_C;
1575   if (!src_y || !dst_argb || width <= 0 || height == 0) {
1576     return -1;
1577   }
1578   // Negative height means invert the image.
1579   if (height < 0) {
1580     height = -height;
1581     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
1582     dst_stride_argb = -dst_stride_argb;
1583   }
1584   // Coalesce rows.
1585   if (src_stride_y == width && dst_stride_argb == width * 4) {
1586     width *= height;
1587     height = 1;
1588     src_stride_y = dst_stride_argb = 0;
1589   }
1590 #if defined(HAS_I400TOARGBROW_SSE2)
1591   if (TestCpuFlag(kCpuHasSSE2)) {
1592     I400ToARGBRow = I400ToARGBRow_Any_SSE2;
1593     if (IS_ALIGNED(width, 8)) {
1594       I400ToARGBRow = I400ToARGBRow_SSE2;
1595     }
1596   }
1597 #endif
1598 #if defined(HAS_I400TOARGBROW_AVX2)
1599   if (TestCpuFlag(kCpuHasAVX2)) {
1600     I400ToARGBRow = I400ToARGBRow_Any_AVX2;
1601     if (IS_ALIGNED(width, 16)) {
1602       I400ToARGBRow = I400ToARGBRow_AVX2;
1603     }
1604   }
1605 #endif
1606 #if defined(HAS_I400TOARGBROW_NEON)
1607   if (TestCpuFlag(kCpuHasNEON)) {
1608     I400ToARGBRow = I400ToARGBRow_Any_NEON;
1609     if (IS_ALIGNED(width, 8)) {
1610       I400ToARGBRow = I400ToARGBRow_NEON;
1611     }
1612   }
1613 #endif
1614 #if defined(HAS_I400TOARGBROW_MMI)
1615   if (TestCpuFlag(kCpuHasMMI)) {
1616     I400ToARGBRow = I400ToARGBRow_Any_MMI;
1617     if (IS_ALIGNED(width, 8)) {
1618       I400ToARGBRow = I400ToARGBRow_MMI;
1619     }
1620   }
1621 #endif
1622 #if defined(HAS_I400TOARGBROW_MSA)
1623   if (TestCpuFlag(kCpuHasMSA)) {
1624     I400ToARGBRow = I400ToARGBRow_Any_MSA;
1625     if (IS_ALIGNED(width, 16)) {
1626       I400ToARGBRow = I400ToARGBRow_MSA;
1627     }
1628   }
1629 #endif
1630 
1631   for (y = 0; y < height; ++y) {
1632     I400ToARGBRow(src_y, dst_argb, yuvconstants, width);
1633     dst_argb += dst_stride_argb;
1634     src_y += src_stride_y;
1635   }
1636   return 0;
1637 }
1638 
1639 // Convert I400 to ARGB.
1640 LIBYUV_API
I400ToARGB(const uint8_t * src_y,int src_stride_y,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1641 int I400ToARGB(const uint8_t* src_y,
1642                int src_stride_y,
1643                uint8_t* dst_argb,
1644                int dst_stride_argb,
1645                int width,
1646                int height) {
1647   return I400ToARGBMatrix(src_y, src_stride_y, dst_argb, dst_stride_argb,
1648                           &kYuvI601Constants, width, height);
1649 }
1650 
1651 // Convert J400 to ARGB.
1652 LIBYUV_API
J400ToARGB(const uint8_t * src_y,int src_stride_y,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1653 int J400ToARGB(const uint8_t* src_y,
1654                int src_stride_y,
1655                uint8_t* dst_argb,
1656                int dst_stride_argb,
1657                int width,
1658                int height) {
1659   int y;
1660   void (*J400ToARGBRow)(const uint8_t* src_y, uint8_t* dst_argb, int width) =
1661       J400ToARGBRow_C;
1662   if (!src_y || !dst_argb || width <= 0 || height == 0) {
1663     return -1;
1664   }
1665   // Negative height means invert the image.
1666   if (height < 0) {
1667     height = -height;
1668     src_y = src_y + (height - 1) * src_stride_y;
1669     src_stride_y = -src_stride_y;
1670   }
1671   // Coalesce rows.
1672   if (src_stride_y == width && dst_stride_argb == width * 4) {
1673     width *= height;
1674     height = 1;
1675     src_stride_y = dst_stride_argb = 0;
1676   }
1677 #if defined(HAS_J400TOARGBROW_SSE2)
1678   if (TestCpuFlag(kCpuHasSSE2)) {
1679     J400ToARGBRow = J400ToARGBRow_Any_SSE2;
1680     if (IS_ALIGNED(width, 8)) {
1681       J400ToARGBRow = J400ToARGBRow_SSE2;
1682     }
1683   }
1684 #endif
1685 #if defined(HAS_J400TOARGBROW_AVX2)
1686   if (TestCpuFlag(kCpuHasAVX2)) {
1687     J400ToARGBRow = J400ToARGBRow_Any_AVX2;
1688     if (IS_ALIGNED(width, 16)) {
1689       J400ToARGBRow = J400ToARGBRow_AVX2;
1690     }
1691   }
1692 #endif
1693 #if defined(HAS_J400TOARGBROW_NEON)
1694   if (TestCpuFlag(kCpuHasNEON)) {
1695     J400ToARGBRow = J400ToARGBRow_Any_NEON;
1696     if (IS_ALIGNED(width, 8)) {
1697       J400ToARGBRow = J400ToARGBRow_NEON;
1698     }
1699   }
1700 #endif
1701 #if defined(HAS_J400TOARGBROW_MMI)
1702   if (TestCpuFlag(kCpuHasMMI)) {
1703     J400ToARGBRow = J400ToARGBRow_Any_MMI;
1704     if (IS_ALIGNED(width, 4)) {
1705       J400ToARGBRow = J400ToARGBRow_MMI;
1706     }
1707   }
1708 #endif
1709 #if defined(HAS_J400TOARGBROW_MSA)
1710   if (TestCpuFlag(kCpuHasMSA)) {
1711     J400ToARGBRow = J400ToARGBRow_Any_MSA;
1712     if (IS_ALIGNED(width, 16)) {
1713       J400ToARGBRow = J400ToARGBRow_MSA;
1714     }
1715   }
1716 #endif
1717   for (y = 0; y < height; ++y) {
1718     J400ToARGBRow(src_y, dst_argb, width);
1719     src_y += src_stride_y;
1720     dst_argb += dst_stride_argb;
1721   }
1722   return 0;
1723 }
1724 
1725 // Shuffle table for converting BGRA to ARGB.
1726 static const uvec8 kShuffleMaskBGRAToARGB = {
1727     3u, 2u, 1u, 0u, 7u, 6u, 5u, 4u, 11u, 10u, 9u, 8u, 15u, 14u, 13u, 12u};
1728 
1729 // Shuffle table for converting ABGR to ARGB.
1730 static const uvec8 kShuffleMaskABGRToARGB = {
1731     2u, 1u, 0u, 3u, 6u, 5u, 4u, 7u, 10u, 9u, 8u, 11u, 14u, 13u, 12u, 15u};
1732 
1733 // Shuffle table for converting RGBA to ARGB.
1734 static const uvec8 kShuffleMaskRGBAToARGB = {
1735     1u, 2u, 3u, 0u, 5u, 6u, 7u, 4u, 9u, 10u, 11u, 8u, 13u, 14u, 15u, 12u};
1736 
1737 // Convert BGRA to ARGB.
1738 LIBYUV_API
BGRAToARGB(const uint8_t * src_bgra,int src_stride_bgra,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1739 int BGRAToARGB(const uint8_t* src_bgra,
1740                int src_stride_bgra,
1741                uint8_t* dst_argb,
1742                int dst_stride_argb,
1743                int width,
1744                int height) {
1745   return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb,
1746                      (const uint8_t*)(&kShuffleMaskBGRAToARGB), width, height);
1747 }
1748 
1749 // Convert ARGB to BGRA (same as BGRAToARGB).
1750 LIBYUV_API
ARGBToBGRA(const uint8_t * src_bgra,int src_stride_bgra,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1751 int ARGBToBGRA(const uint8_t* src_bgra,
1752                int src_stride_bgra,
1753                uint8_t* dst_argb,
1754                int dst_stride_argb,
1755                int width,
1756                int height) {
1757   return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb,
1758                      (const uint8_t*)(&kShuffleMaskBGRAToARGB), width, height);
1759 }
1760 
1761 // Convert ABGR to ARGB.
1762 LIBYUV_API
ABGRToARGB(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1763 int ABGRToARGB(const uint8_t* src_abgr,
1764                int src_stride_abgr,
1765                uint8_t* dst_argb,
1766                int dst_stride_argb,
1767                int width,
1768                int height) {
1769   return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb,
1770                      (const uint8_t*)(&kShuffleMaskABGRToARGB), width, height);
1771 }
1772 
1773 // Convert ARGB to ABGR to (same as ABGRToARGB).
1774 LIBYUV_API
ARGBToABGR(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1775 int ARGBToABGR(const uint8_t* src_abgr,
1776                int src_stride_abgr,
1777                uint8_t* dst_argb,
1778                int dst_stride_argb,
1779                int width,
1780                int height) {
1781   return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb,
1782                      (const uint8_t*)(&kShuffleMaskABGRToARGB), width, height);
1783 }
1784 
1785 // Convert RGBA to ARGB.
1786 LIBYUV_API
RGBAToARGB(const uint8_t * src_rgba,int src_stride_rgba,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1787 int RGBAToARGB(const uint8_t* src_rgba,
1788                int src_stride_rgba,
1789                uint8_t* dst_argb,
1790                int dst_stride_argb,
1791                int width,
1792                int height) {
1793   return ARGBShuffle(src_rgba, src_stride_rgba, dst_argb, dst_stride_argb,
1794                      (const uint8_t*)(&kShuffleMaskRGBAToARGB), width, height);
1795 }
1796 
1797 // Convert RGB24 to ARGB.
1798 LIBYUV_API
RGB24ToARGB(const uint8_t * src_rgb24,int src_stride_rgb24,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1799 int RGB24ToARGB(const uint8_t* src_rgb24,
1800                 int src_stride_rgb24,
1801                 uint8_t* dst_argb,
1802                 int dst_stride_argb,
1803                 int width,
1804                 int height) {
1805   int y;
1806   void (*RGB24ToARGBRow)(const uint8_t* src_rgb, uint8_t* dst_argb, int width) =
1807       RGB24ToARGBRow_C;
1808   if (!src_rgb24 || !dst_argb || width <= 0 || height == 0) {
1809     return -1;
1810   }
1811   // Negative height means invert the image.
1812   if (height < 0) {
1813     height = -height;
1814     src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24;
1815     src_stride_rgb24 = -src_stride_rgb24;
1816   }
1817   // Coalesce rows.
1818   if (src_stride_rgb24 == width * 3 && dst_stride_argb == width * 4) {
1819     width *= height;
1820     height = 1;
1821     src_stride_rgb24 = dst_stride_argb = 0;
1822   }
1823 #if defined(HAS_RGB24TOARGBROW_SSSE3)
1824   if (TestCpuFlag(kCpuHasSSSE3)) {
1825     RGB24ToARGBRow = RGB24ToARGBRow_Any_SSSE3;
1826     if (IS_ALIGNED(width, 16)) {
1827       RGB24ToARGBRow = RGB24ToARGBRow_SSSE3;
1828     }
1829   }
1830 #endif
1831 #if defined(HAS_RGB24TOARGBROW_NEON)
1832   if (TestCpuFlag(kCpuHasNEON)) {
1833     RGB24ToARGBRow = RGB24ToARGBRow_Any_NEON;
1834     if (IS_ALIGNED(width, 8)) {
1835       RGB24ToARGBRow = RGB24ToARGBRow_NEON;
1836     }
1837   }
1838 #endif
1839 #if defined(HAS_RGB24TOARGBROW_MMI)
1840   if (TestCpuFlag(kCpuHasMMI)) {
1841     RGB24ToARGBRow = RGB24ToARGBRow_Any_MMI;
1842     if (IS_ALIGNED(width, 4)) {
1843       RGB24ToARGBRow = RGB24ToARGBRow_MMI;
1844     }
1845   }
1846 #endif
1847 #if defined(HAS_RGB24TOARGBROW_MSA)
1848   if (TestCpuFlag(kCpuHasMSA)) {
1849     RGB24ToARGBRow = RGB24ToARGBRow_Any_MSA;
1850     if (IS_ALIGNED(width, 16)) {
1851       RGB24ToARGBRow = RGB24ToARGBRow_MSA;
1852     }
1853   }
1854 #endif
1855 
1856   for (y = 0; y < height; ++y) {
1857     RGB24ToARGBRow(src_rgb24, dst_argb, width);
1858     src_rgb24 += src_stride_rgb24;
1859     dst_argb += dst_stride_argb;
1860   }
1861   return 0;
1862 }
1863 
1864 // Convert RAW to ARGB.
1865 LIBYUV_API
RAWToARGB(const uint8_t * src_raw,int src_stride_raw,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1866 int RAWToARGB(const uint8_t* src_raw,
1867               int src_stride_raw,
1868               uint8_t* dst_argb,
1869               int dst_stride_argb,
1870               int width,
1871               int height) {
1872   int y;
1873   void (*RAWToARGBRow)(const uint8_t* src_rgb, uint8_t* dst_argb, int width) =
1874       RAWToARGBRow_C;
1875   if (!src_raw || !dst_argb || width <= 0 || height == 0) {
1876     return -1;
1877   }
1878   // Negative height means invert the image.
1879   if (height < 0) {
1880     height = -height;
1881     src_raw = src_raw + (height - 1) * src_stride_raw;
1882     src_stride_raw = -src_stride_raw;
1883   }
1884   // Coalesce rows.
1885   if (src_stride_raw == width * 3 && dst_stride_argb == width * 4) {
1886     width *= height;
1887     height = 1;
1888     src_stride_raw = dst_stride_argb = 0;
1889   }
1890 #if defined(HAS_RAWTOARGBROW_SSSE3)
1891   if (TestCpuFlag(kCpuHasSSSE3)) {
1892     RAWToARGBRow = RAWToARGBRow_Any_SSSE3;
1893     if (IS_ALIGNED(width, 16)) {
1894       RAWToARGBRow = RAWToARGBRow_SSSE3;
1895     }
1896   }
1897 #endif
1898 #if defined(HAS_RAWTOARGBROW_NEON)
1899   if (TestCpuFlag(kCpuHasNEON)) {
1900     RAWToARGBRow = RAWToARGBRow_Any_NEON;
1901     if (IS_ALIGNED(width, 8)) {
1902       RAWToARGBRow = RAWToARGBRow_NEON;
1903     }
1904   }
1905 #endif
1906 #if defined(HAS_RAWTOARGBROW_MMI)
1907   if (TestCpuFlag(kCpuHasMMI)) {
1908     RAWToARGBRow = RAWToARGBRow_Any_MMI;
1909     if (IS_ALIGNED(width, 4)) {
1910       RAWToARGBRow = RAWToARGBRow_MMI;
1911     }
1912   }
1913 #endif
1914 #if defined(HAS_RAWTOARGBROW_MSA)
1915   if (TestCpuFlag(kCpuHasMSA)) {
1916     RAWToARGBRow = RAWToARGBRow_Any_MSA;
1917     if (IS_ALIGNED(width, 16)) {
1918       RAWToARGBRow = RAWToARGBRow_MSA;
1919     }
1920   }
1921 #endif
1922 
1923   for (y = 0; y < height; ++y) {
1924     RAWToARGBRow(src_raw, dst_argb, width);
1925     src_raw += src_stride_raw;
1926     dst_argb += dst_stride_argb;
1927   }
1928   return 0;
1929 }
1930 
1931 // Convert RAW to RGBA.
1932 LIBYUV_API
RAWToRGBA(const uint8_t * src_raw,int src_stride_raw,uint8_t * dst_rgba,int dst_stride_rgba,int width,int height)1933 int RAWToRGBA(const uint8_t* src_raw,
1934               int src_stride_raw,
1935               uint8_t* dst_rgba,
1936               int dst_stride_rgba,
1937               int width,
1938               int height) {
1939   int y;
1940   void (*RAWToRGBARow)(const uint8_t* src_rgb, uint8_t* dst_rgba, int width) =
1941       RAWToRGBARow_C;
1942   if (!src_raw || !dst_rgba || width <= 0 || height == 0) {
1943     return -1;
1944   }
1945   // Negative height means invert the image.
1946   if (height < 0) {
1947     height = -height;
1948     src_raw = src_raw + (height - 1) * src_stride_raw;
1949     src_stride_raw = -src_stride_raw;
1950   }
1951   // Coalesce rows.
1952   if (src_stride_raw == width * 3 && dst_stride_rgba == width * 4) {
1953     width *= height;
1954     height = 1;
1955     src_stride_raw = dst_stride_rgba = 0;
1956   }
1957 #if defined(HAS_RAWTORGBAROW_SSSE3)
1958   if (TestCpuFlag(kCpuHasSSSE3)) {
1959     RAWToRGBARow = RAWToRGBARow_Any_SSSE3;
1960     if (IS_ALIGNED(width, 16)) {
1961       RAWToRGBARow = RAWToRGBARow_SSSE3;
1962     }
1963   }
1964 #endif
1965 #if defined(HAS_RAWTORGBAROW_NEON)
1966   if (TestCpuFlag(kCpuHasNEON)) {
1967     RAWToRGBARow = RAWToRGBARow_Any_NEON;
1968     if (IS_ALIGNED(width, 8)) {
1969       RAWToRGBARow = RAWToRGBARow_NEON;
1970     }
1971   }
1972 #endif
1973 
1974   for (y = 0; y < height; ++y) {
1975     RAWToRGBARow(src_raw, dst_rgba, width);
1976     src_raw += src_stride_raw;
1977     dst_rgba += dst_stride_rgba;
1978   }
1979   return 0;
1980 }
1981 
1982 // Convert RGB565 to ARGB.
1983 LIBYUV_API
RGB565ToARGB(const uint8_t * src_rgb565,int src_stride_rgb565,uint8_t * dst_argb,int dst_stride_argb,int width,int height)1984 int RGB565ToARGB(const uint8_t* src_rgb565,
1985                  int src_stride_rgb565,
1986                  uint8_t* dst_argb,
1987                  int dst_stride_argb,
1988                  int width,
1989                  int height) {
1990   int y;
1991   void (*RGB565ToARGBRow)(const uint8_t* src_rgb565, uint8_t* dst_argb,
1992                           int width) = RGB565ToARGBRow_C;
1993   if (!src_rgb565 || !dst_argb || width <= 0 || height == 0) {
1994     return -1;
1995   }
1996   // Negative height means invert the image.
1997   if (height < 0) {
1998     height = -height;
1999     src_rgb565 = src_rgb565 + (height - 1) * src_stride_rgb565;
2000     src_stride_rgb565 = -src_stride_rgb565;
2001   }
2002   // Coalesce rows.
2003   if (src_stride_rgb565 == width * 2 && dst_stride_argb == width * 4) {
2004     width *= height;
2005     height = 1;
2006     src_stride_rgb565 = dst_stride_argb = 0;
2007   }
2008 #if defined(HAS_RGB565TOARGBROW_SSE2)
2009   if (TestCpuFlag(kCpuHasSSE2)) {
2010     RGB565ToARGBRow = RGB565ToARGBRow_Any_SSE2;
2011     if (IS_ALIGNED(width, 8)) {
2012       RGB565ToARGBRow = RGB565ToARGBRow_SSE2;
2013     }
2014   }
2015 #endif
2016 #if defined(HAS_RGB565TOARGBROW_AVX2)
2017   if (TestCpuFlag(kCpuHasAVX2)) {
2018     RGB565ToARGBRow = RGB565ToARGBRow_Any_AVX2;
2019     if (IS_ALIGNED(width, 16)) {
2020       RGB565ToARGBRow = RGB565ToARGBRow_AVX2;
2021     }
2022   }
2023 #endif
2024 #if defined(HAS_RGB565TOARGBROW_NEON)
2025   if (TestCpuFlag(kCpuHasNEON)) {
2026     RGB565ToARGBRow = RGB565ToARGBRow_Any_NEON;
2027     if (IS_ALIGNED(width, 8)) {
2028       RGB565ToARGBRow = RGB565ToARGBRow_NEON;
2029     }
2030   }
2031 #endif
2032 #if defined(HAS_RGB565TOARGBROW_MMI)
2033   if (TestCpuFlag(kCpuHasMMI)) {
2034     RGB565ToARGBRow = RGB565ToARGBRow_Any_MMI;
2035     if (IS_ALIGNED(width, 4)) {
2036       RGB565ToARGBRow = RGB565ToARGBRow_MMI;
2037     }
2038   }
2039 #endif
2040 #if defined(HAS_RGB565TOARGBROW_MSA)
2041   if (TestCpuFlag(kCpuHasMSA)) {
2042     RGB565ToARGBRow = RGB565ToARGBRow_Any_MSA;
2043     if (IS_ALIGNED(width, 16)) {
2044       RGB565ToARGBRow = RGB565ToARGBRow_MSA;
2045     }
2046   }
2047 #endif
2048 
2049   for (y = 0; y < height; ++y) {
2050     RGB565ToARGBRow(src_rgb565, dst_argb, width);
2051     src_rgb565 += src_stride_rgb565;
2052     dst_argb += dst_stride_argb;
2053   }
2054   return 0;
2055 }
2056 
2057 // Convert ARGB1555 to ARGB.
2058 LIBYUV_API
ARGB1555ToARGB(const uint8_t * src_argb1555,int src_stride_argb1555,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2059 int ARGB1555ToARGB(const uint8_t* src_argb1555,
2060                    int src_stride_argb1555,
2061                    uint8_t* dst_argb,
2062                    int dst_stride_argb,
2063                    int width,
2064                    int height) {
2065   int y;
2066   void (*ARGB1555ToARGBRow)(const uint8_t* src_argb1555, uint8_t* dst_argb,
2067                             int width) = ARGB1555ToARGBRow_C;
2068   if (!src_argb1555 || !dst_argb || width <= 0 || height == 0) {
2069     return -1;
2070   }
2071   // Negative height means invert the image.
2072   if (height < 0) {
2073     height = -height;
2074     src_argb1555 = src_argb1555 + (height - 1) * src_stride_argb1555;
2075     src_stride_argb1555 = -src_stride_argb1555;
2076   }
2077   // Coalesce rows.
2078   if (src_stride_argb1555 == width * 2 && dst_stride_argb == width * 4) {
2079     width *= height;
2080     height = 1;
2081     src_stride_argb1555 = dst_stride_argb = 0;
2082   }
2083 #if defined(HAS_ARGB1555TOARGBROW_SSE2)
2084   if (TestCpuFlag(kCpuHasSSE2)) {
2085     ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_SSE2;
2086     if (IS_ALIGNED(width, 8)) {
2087       ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2;
2088     }
2089   }
2090 #endif
2091 #if defined(HAS_ARGB1555TOARGBROW_AVX2)
2092   if (TestCpuFlag(kCpuHasAVX2)) {
2093     ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_AVX2;
2094     if (IS_ALIGNED(width, 16)) {
2095       ARGB1555ToARGBRow = ARGB1555ToARGBRow_AVX2;
2096     }
2097   }
2098 #endif
2099 #if defined(HAS_ARGB1555TOARGBROW_NEON)
2100   if (TestCpuFlag(kCpuHasNEON)) {
2101     ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_NEON;
2102     if (IS_ALIGNED(width, 8)) {
2103       ARGB1555ToARGBRow = ARGB1555ToARGBRow_NEON;
2104     }
2105   }
2106 #endif
2107 #if defined(HAS_ARGB1555TOARGBROW_MMI)
2108   if (TestCpuFlag(kCpuHasMMI)) {
2109     ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_MMI;
2110     if (IS_ALIGNED(width, 4)) {
2111       ARGB1555ToARGBRow = ARGB1555ToARGBRow_MMI;
2112     }
2113   }
2114 #endif
2115 #if defined(HAS_ARGB1555TOARGBROW_MSA)
2116   if (TestCpuFlag(kCpuHasMSA)) {
2117     ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_MSA;
2118     if (IS_ALIGNED(width, 16)) {
2119       ARGB1555ToARGBRow = ARGB1555ToARGBRow_MSA;
2120     }
2121   }
2122 #endif
2123 
2124   for (y = 0; y < height; ++y) {
2125     ARGB1555ToARGBRow(src_argb1555, dst_argb, width);
2126     src_argb1555 += src_stride_argb1555;
2127     dst_argb += dst_stride_argb;
2128   }
2129   return 0;
2130 }
2131 
2132 // Convert ARGB4444 to ARGB.
2133 LIBYUV_API
ARGB4444ToARGB(const uint8_t * src_argb4444,int src_stride_argb4444,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2134 int ARGB4444ToARGB(const uint8_t* src_argb4444,
2135                    int src_stride_argb4444,
2136                    uint8_t* dst_argb,
2137                    int dst_stride_argb,
2138                    int width,
2139                    int height) {
2140   int y;
2141   void (*ARGB4444ToARGBRow)(const uint8_t* src_argb4444, uint8_t* dst_argb,
2142                             int width) = ARGB4444ToARGBRow_C;
2143   if (!src_argb4444 || !dst_argb || width <= 0 || height == 0) {
2144     return -1;
2145   }
2146   // Negative height means invert the image.
2147   if (height < 0) {
2148     height = -height;
2149     src_argb4444 = src_argb4444 + (height - 1) * src_stride_argb4444;
2150     src_stride_argb4444 = -src_stride_argb4444;
2151   }
2152   // Coalesce rows.
2153   if (src_stride_argb4444 == width * 2 && dst_stride_argb == width * 4) {
2154     width *= height;
2155     height = 1;
2156     src_stride_argb4444 = dst_stride_argb = 0;
2157   }
2158 #if defined(HAS_ARGB4444TOARGBROW_SSE2)
2159   if (TestCpuFlag(kCpuHasSSE2)) {
2160     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_SSE2;
2161     if (IS_ALIGNED(width, 8)) {
2162       ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2;
2163     }
2164   }
2165 #endif
2166 #if defined(HAS_ARGB4444TOARGBROW_AVX2)
2167   if (TestCpuFlag(kCpuHasAVX2)) {
2168     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_AVX2;
2169     if (IS_ALIGNED(width, 16)) {
2170       ARGB4444ToARGBRow = ARGB4444ToARGBRow_AVX2;
2171     }
2172   }
2173 #endif
2174 #if defined(HAS_ARGB4444TOARGBROW_NEON)
2175   if (TestCpuFlag(kCpuHasNEON)) {
2176     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_NEON;
2177     if (IS_ALIGNED(width, 8)) {
2178       ARGB4444ToARGBRow = ARGB4444ToARGBRow_NEON;
2179     }
2180   }
2181 #endif
2182 #if defined(HAS_ARGB4444TOARGBROW_MMI)
2183   if (TestCpuFlag(kCpuHasMMI)) {
2184     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_MMI;
2185     if (IS_ALIGNED(width, 4)) {
2186       ARGB4444ToARGBRow = ARGB4444ToARGBRow_MMI;
2187     }
2188   }
2189 #endif
2190 #if defined(HAS_ARGB4444TOARGBROW_MSA)
2191   if (TestCpuFlag(kCpuHasMSA)) {
2192     ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_MSA;
2193     if (IS_ALIGNED(width, 16)) {
2194       ARGB4444ToARGBRow = ARGB4444ToARGBRow_MSA;
2195     }
2196   }
2197 #endif
2198 
2199   for (y = 0; y < height; ++y) {
2200     ARGB4444ToARGBRow(src_argb4444, dst_argb, width);
2201     src_argb4444 += src_stride_argb4444;
2202     dst_argb += dst_stride_argb;
2203   }
2204   return 0;
2205 }
2206 
2207 // Convert AR30 to ARGB.
2208 LIBYUV_API
AR30ToARGB(const uint8_t * src_ar30,int src_stride_ar30,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2209 int AR30ToARGB(const uint8_t* src_ar30,
2210                int src_stride_ar30,
2211                uint8_t* dst_argb,
2212                int dst_stride_argb,
2213                int width,
2214                int height) {
2215   int y;
2216   if (!src_ar30 || !dst_argb || width <= 0 || height == 0) {
2217     return -1;
2218   }
2219   // Negative height means invert the image.
2220   if (height < 0) {
2221     height = -height;
2222     src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
2223     src_stride_ar30 = -src_stride_ar30;
2224   }
2225   // Coalesce rows.
2226   if (src_stride_ar30 == width * 4 && dst_stride_argb == width * 4) {
2227     width *= height;
2228     height = 1;
2229     src_stride_ar30 = dst_stride_argb = 0;
2230   }
2231   for (y = 0; y < height; ++y) {
2232     AR30ToARGBRow_C(src_ar30, dst_argb, width);
2233     src_ar30 += src_stride_ar30;
2234     dst_argb += dst_stride_argb;
2235   }
2236   return 0;
2237 }
2238 
2239 // Convert AR30 to ABGR.
2240 LIBYUV_API
AR30ToABGR(const uint8_t * src_ar30,int src_stride_ar30,uint8_t * dst_abgr,int dst_stride_abgr,int width,int height)2241 int AR30ToABGR(const uint8_t* src_ar30,
2242                int src_stride_ar30,
2243                uint8_t* dst_abgr,
2244                int dst_stride_abgr,
2245                int width,
2246                int height) {
2247   int y;
2248   if (!src_ar30 || !dst_abgr || width <= 0 || height == 0) {
2249     return -1;
2250   }
2251   // Negative height means invert the image.
2252   if (height < 0) {
2253     height = -height;
2254     src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
2255     src_stride_ar30 = -src_stride_ar30;
2256   }
2257   // Coalesce rows.
2258   if (src_stride_ar30 == width * 4 && dst_stride_abgr == width * 4) {
2259     width *= height;
2260     height = 1;
2261     src_stride_ar30 = dst_stride_abgr = 0;
2262   }
2263   for (y = 0; y < height; ++y) {
2264     AR30ToABGRRow_C(src_ar30, dst_abgr, width);
2265     src_ar30 += src_stride_ar30;
2266     dst_abgr += dst_stride_abgr;
2267   }
2268   return 0;
2269 }
2270 
2271 // Convert AR30 to AB30.
2272 LIBYUV_API
AR30ToAB30(const uint8_t * src_ar30,int src_stride_ar30,uint8_t * dst_ab30,int dst_stride_ab30,int width,int height)2273 int AR30ToAB30(const uint8_t* src_ar30,
2274                int src_stride_ar30,
2275                uint8_t* dst_ab30,
2276                int dst_stride_ab30,
2277                int width,
2278                int height) {
2279   int y;
2280   if (!src_ar30 || !dst_ab30 || width <= 0 || height == 0) {
2281     return -1;
2282   }
2283   // Negative height means invert the image.
2284   if (height < 0) {
2285     height = -height;
2286     src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
2287     src_stride_ar30 = -src_stride_ar30;
2288   }
2289   // Coalesce rows.
2290   if (src_stride_ar30 == width * 4 && dst_stride_ab30 == width * 4) {
2291     width *= height;
2292     height = 1;
2293     src_stride_ar30 = dst_stride_ab30 = 0;
2294   }
2295   for (y = 0; y < height; ++y) {
2296     AR30ToAB30Row_C(src_ar30, dst_ab30, width);
2297     src_ar30 += src_stride_ar30;
2298     dst_ab30 += dst_stride_ab30;
2299   }
2300   return 0;
2301 }
2302 
2303 // Convert NV12 to ARGB with matrix.
2304 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)2305 int NV12ToARGBMatrix(const uint8_t* src_y,
2306                      int src_stride_y,
2307                      const uint8_t* src_uv,
2308                      int src_stride_uv,
2309                      uint8_t* dst_argb,
2310                      int dst_stride_argb,
2311                      const struct YuvConstants* yuvconstants,
2312                      int width,
2313                      int height) {
2314   int y;
2315   void (*NV12ToARGBRow)(
2316       const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
2317       const struct YuvConstants* yuvconstants, int width) = NV12ToARGBRow_C;
2318   if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) {
2319     return -1;
2320   }
2321   // Negative height means invert the image.
2322   if (height < 0) {
2323     height = -height;
2324     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2325     dst_stride_argb = -dst_stride_argb;
2326   }
2327 #if defined(HAS_NV12TOARGBROW_SSSE3)
2328   if (TestCpuFlag(kCpuHasSSSE3)) {
2329     NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
2330     if (IS_ALIGNED(width, 8)) {
2331       NV12ToARGBRow = NV12ToARGBRow_SSSE3;
2332     }
2333   }
2334 #endif
2335 #if defined(HAS_NV12TOARGBROW_AVX2)
2336   if (TestCpuFlag(kCpuHasAVX2)) {
2337     NV12ToARGBRow = NV12ToARGBRow_Any_AVX2;
2338     if (IS_ALIGNED(width, 16)) {
2339       NV12ToARGBRow = NV12ToARGBRow_AVX2;
2340     }
2341   }
2342 #endif
2343 #if defined(HAS_NV12TOARGBROW_NEON)
2344   if (TestCpuFlag(kCpuHasNEON)) {
2345     NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
2346     if (IS_ALIGNED(width, 8)) {
2347       NV12ToARGBRow = NV12ToARGBRow_NEON;
2348     }
2349   }
2350 #endif
2351 #if defined(HAS_NV12TOARGBROW_MMI)
2352   if (TestCpuFlag(kCpuHasMMI)) {
2353     NV12ToARGBRow = NV12ToARGBRow_Any_MMI;
2354     if (IS_ALIGNED(width, 4)) {
2355       NV12ToARGBRow = NV12ToARGBRow_MMI;
2356     }
2357   }
2358 #endif
2359 #if defined(HAS_NV12TOARGBROW_MSA)
2360   if (TestCpuFlag(kCpuHasMSA)) {
2361     NV12ToARGBRow = NV12ToARGBRow_Any_MSA;
2362     if (IS_ALIGNED(width, 8)) {
2363       NV12ToARGBRow = NV12ToARGBRow_MSA;
2364     }
2365   }
2366 #endif
2367 
2368   for (y = 0; y < height; ++y) {
2369     NV12ToARGBRow(src_y, src_uv, dst_argb, yuvconstants, width);
2370     dst_argb += dst_stride_argb;
2371     src_y += src_stride_y;
2372     if (y & 1) {
2373       src_uv += src_stride_uv;
2374     }
2375   }
2376   return 0;
2377 }
2378 
2379 // Convert NV21 to ARGB with matrix.
2380 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)2381 int NV21ToARGBMatrix(const uint8_t* src_y,
2382                      int src_stride_y,
2383                      const uint8_t* src_vu,
2384                      int src_stride_vu,
2385                      uint8_t* dst_argb,
2386                      int dst_stride_argb,
2387                      const struct YuvConstants* yuvconstants,
2388                      int width,
2389                      int height) {
2390   int y;
2391   void (*NV21ToARGBRow)(
2392       const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
2393       const struct YuvConstants* yuvconstants, int width) = NV21ToARGBRow_C;
2394   if (!src_y || !src_vu || !dst_argb || width <= 0 || height == 0) {
2395     return -1;
2396   }
2397   // Negative height means invert the image.
2398   if (height < 0) {
2399     height = -height;
2400     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2401     dst_stride_argb = -dst_stride_argb;
2402   }
2403 #if defined(HAS_NV21TOARGBROW_SSSE3)
2404   if (TestCpuFlag(kCpuHasSSSE3)) {
2405     NV21ToARGBRow = NV21ToARGBRow_Any_SSSE3;
2406     if (IS_ALIGNED(width, 8)) {
2407       NV21ToARGBRow = NV21ToARGBRow_SSSE3;
2408     }
2409   }
2410 #endif
2411 #if defined(HAS_NV21TOARGBROW_AVX2)
2412   if (TestCpuFlag(kCpuHasAVX2)) {
2413     NV21ToARGBRow = NV21ToARGBRow_Any_AVX2;
2414     if (IS_ALIGNED(width, 16)) {
2415       NV21ToARGBRow = NV21ToARGBRow_AVX2;
2416     }
2417   }
2418 #endif
2419 #if defined(HAS_NV21TOARGBROW_NEON)
2420   if (TestCpuFlag(kCpuHasNEON)) {
2421     NV21ToARGBRow = NV21ToARGBRow_Any_NEON;
2422     if (IS_ALIGNED(width, 8)) {
2423       NV21ToARGBRow = NV21ToARGBRow_NEON;
2424     }
2425   }
2426 #endif
2427 #if defined(HAS_NV21TOARGBROW_MMI)
2428   if (TestCpuFlag(kCpuHasMMI)) {
2429     NV21ToARGBRow = NV21ToARGBRow_Any_MMI;
2430     if (IS_ALIGNED(width, 4)) {
2431       NV21ToARGBRow = NV21ToARGBRow_MMI;
2432     }
2433   }
2434 #endif
2435 #if defined(HAS_NV21TOARGBROW_MSA)
2436   if (TestCpuFlag(kCpuHasMSA)) {
2437     NV21ToARGBRow = NV21ToARGBRow_Any_MSA;
2438     if (IS_ALIGNED(width, 8)) {
2439       NV21ToARGBRow = NV21ToARGBRow_MSA;
2440     }
2441   }
2442 #endif
2443 
2444   for (y = 0; y < height; ++y) {
2445     NV21ToARGBRow(src_y, src_vu, dst_argb, yuvconstants, width);
2446     dst_argb += dst_stride_argb;
2447     src_y += src_stride_y;
2448     if (y & 1) {
2449       src_vu += src_stride_vu;
2450     }
2451   }
2452   return 0;
2453 }
2454 
2455 // Convert NV12 to ARGB.
2456 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)2457 int NV12ToARGB(const uint8_t* src_y,
2458                int src_stride_y,
2459                const uint8_t* src_uv,
2460                int src_stride_uv,
2461                uint8_t* dst_argb,
2462                int dst_stride_argb,
2463                int width,
2464                int height) {
2465   return NV12ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_argb,
2466                           dst_stride_argb, &kYuvI601Constants, width, height);
2467 }
2468 
2469 // Convert NV21 to ARGB.
2470 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)2471 int NV21ToARGB(const uint8_t* src_y,
2472                int src_stride_y,
2473                const uint8_t* src_vu,
2474                int src_stride_vu,
2475                uint8_t* dst_argb,
2476                int dst_stride_argb,
2477                int width,
2478                int height) {
2479   return NV21ToARGBMatrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_argb,
2480                           dst_stride_argb, &kYuvI601Constants, width, height);
2481 }
2482 
2483 // Convert NV12 to ABGR.
2484 // To output ABGR instead of ARGB swap the UV and use a mirrored yuv matrix.
2485 // To swap the UV use NV12 instead of NV21.LIBYUV_API
2486 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)2487 int NV12ToABGR(const uint8_t* src_y,
2488                int src_stride_y,
2489                const uint8_t* src_uv,
2490                int src_stride_uv,
2491                uint8_t* dst_abgr,
2492                int dst_stride_abgr,
2493                int width,
2494                int height) {
2495   return NV21ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_abgr,
2496                           dst_stride_abgr, &kYvuI601Constants, width, height);
2497 }
2498 
2499 // Convert NV21 to ABGR.
2500 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)2501 int NV21ToABGR(const uint8_t* src_y,
2502                int src_stride_y,
2503                const uint8_t* src_vu,
2504                int src_stride_vu,
2505                uint8_t* dst_abgr,
2506                int dst_stride_abgr,
2507                int width,
2508                int height) {
2509   return NV12ToARGBMatrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_abgr,
2510                           dst_stride_abgr, &kYvuI601Constants, width, height);
2511 }
2512 
2513 // TODO(fbarchard): Consider SSSE3 2 step conversion.
2514 // Convert NV12 to RGB24 with matrix.
2515 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)2516 int NV12ToRGB24Matrix(const uint8_t* src_y,
2517                       int src_stride_y,
2518                       const uint8_t* src_uv,
2519                       int src_stride_uv,
2520                       uint8_t* dst_rgb24,
2521                       int dst_stride_rgb24,
2522                       const struct YuvConstants* yuvconstants,
2523                       int width,
2524                       int height) {
2525   int y;
2526   void (*NV12ToRGB24Row)(
2527       const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
2528       const struct YuvConstants* yuvconstants, int width) = NV12ToRGB24Row_C;
2529   if (!src_y || !src_uv || !dst_rgb24 || width <= 0 || height == 0) {
2530     return -1;
2531   }
2532   // Negative height means invert the image.
2533   if (height < 0) {
2534     height = -height;
2535     dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
2536     dst_stride_rgb24 = -dst_stride_rgb24;
2537   }
2538 #if defined(HAS_NV12TORGB24ROW_NEON)
2539   if (TestCpuFlag(kCpuHasNEON)) {
2540     NV12ToRGB24Row = NV12ToRGB24Row_Any_NEON;
2541     if (IS_ALIGNED(width, 8)) {
2542       NV12ToRGB24Row = NV12ToRGB24Row_NEON;
2543     }
2544   }
2545 #endif
2546 #if defined(HAS_NV12TORGB24ROW_SSSE3)
2547   if (TestCpuFlag(kCpuHasSSSE3)) {
2548     NV12ToRGB24Row = NV12ToRGB24Row_Any_SSSE3;
2549     if (IS_ALIGNED(width, 16)) {
2550       NV12ToRGB24Row = NV12ToRGB24Row_SSSE3;
2551     }
2552   }
2553 #endif
2554 #if defined(HAS_NV12TORGB24ROW_AVX2)
2555   if (TestCpuFlag(kCpuHasAVX2)) {
2556     NV12ToRGB24Row = NV12ToRGB24Row_Any_AVX2;
2557     if (IS_ALIGNED(width, 32)) {
2558       NV12ToRGB24Row = NV12ToRGB24Row_AVX2;
2559     }
2560   }
2561 #endif
2562 #if defined(HAS_NV12TORGB24ROW_MMI)
2563   if (TestCpuFlag(kCpuHasMMI)) {
2564     NV12ToRGB24Row = NV12ToRGB24Row_Any_MMI;
2565     if (IS_ALIGNED(width, 8)) {
2566       NV12ToRGB24Row = NV12ToRGB24Row_MMI;
2567     }
2568   }
2569 #endif
2570 
2571   for (y = 0; y < height; ++y) {
2572     NV12ToRGB24Row(src_y, src_uv, dst_rgb24, yuvconstants, width);
2573     dst_rgb24 += dst_stride_rgb24;
2574     src_y += src_stride_y;
2575     if (y & 1) {
2576       src_uv += src_stride_uv;
2577     }
2578   }
2579   return 0;
2580 }
2581 
2582 // Convert NV21 to RGB24 with matrix.
2583 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)2584 int NV21ToRGB24Matrix(const uint8_t* src_y,
2585                       int src_stride_y,
2586                       const uint8_t* src_vu,
2587                       int src_stride_vu,
2588                       uint8_t* dst_rgb24,
2589                       int dst_stride_rgb24,
2590                       const struct YuvConstants* yuvconstants,
2591                       int width,
2592                       int height) {
2593   int y;
2594   void (*NV21ToRGB24Row)(
2595       const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
2596       const struct YuvConstants* yuvconstants, int width) = NV21ToRGB24Row_C;
2597   if (!src_y || !src_vu || !dst_rgb24 || width <= 0 || height == 0) {
2598     return -1;
2599   }
2600   // Negative height means invert the image.
2601   if (height < 0) {
2602     height = -height;
2603     dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
2604     dst_stride_rgb24 = -dst_stride_rgb24;
2605   }
2606 #if defined(HAS_NV21TORGB24ROW_NEON)
2607   if (TestCpuFlag(kCpuHasNEON)) {
2608     NV21ToRGB24Row = NV21ToRGB24Row_Any_NEON;
2609     if (IS_ALIGNED(width, 8)) {
2610       NV21ToRGB24Row = NV21ToRGB24Row_NEON;
2611     }
2612   }
2613 #endif
2614 #if defined(HAS_NV21TORGB24ROW_SSSE3)
2615   if (TestCpuFlag(kCpuHasSSSE3)) {
2616     NV21ToRGB24Row = NV21ToRGB24Row_Any_SSSE3;
2617     if (IS_ALIGNED(width, 16)) {
2618       NV21ToRGB24Row = NV21ToRGB24Row_SSSE3;
2619     }
2620   }
2621 #endif
2622 #if defined(HAS_NV21TORGB24ROW_AVX2)
2623   if (TestCpuFlag(kCpuHasAVX2)) {
2624     NV21ToRGB24Row = NV21ToRGB24Row_Any_AVX2;
2625     if (IS_ALIGNED(width, 32)) {
2626       NV21ToRGB24Row = NV21ToRGB24Row_AVX2;
2627     }
2628   }
2629 #endif
2630 #if defined(HAS_NV21TORGB24ROW_MMI)
2631   if (TestCpuFlag(kCpuHasMMI)) {
2632     NV21ToRGB24Row = NV21ToRGB24Row_Any_MMI;
2633     if (IS_ALIGNED(width, 8)) {
2634       NV21ToRGB24Row = NV21ToRGB24Row_MMI;
2635     }
2636   }
2637 #endif
2638 
2639   for (y = 0; y < height; ++y) {
2640     NV21ToRGB24Row(src_y, src_vu, dst_rgb24, yuvconstants, width);
2641     dst_rgb24 += dst_stride_rgb24;
2642     src_y += src_stride_y;
2643     if (y & 1) {
2644       src_vu += src_stride_vu;
2645     }
2646   }
2647   return 0;
2648 }
2649 
2650 // Convert NV12 to RGB24.
2651 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)2652 int NV12ToRGB24(const uint8_t* src_y,
2653                 int src_stride_y,
2654                 const uint8_t* src_uv,
2655                 int src_stride_uv,
2656                 uint8_t* dst_rgb24,
2657                 int dst_stride_rgb24,
2658                 int width,
2659                 int height) {
2660   return NV12ToRGB24Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
2661                            dst_rgb24, dst_stride_rgb24, &kYuvI601Constants,
2662                            width, height);
2663 }
2664 
2665 // Convert NV21 to RGB24.
2666 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)2667 int NV21ToRGB24(const uint8_t* src_y,
2668                 int src_stride_y,
2669                 const uint8_t* src_vu,
2670                 int src_stride_vu,
2671                 uint8_t* dst_rgb24,
2672                 int dst_stride_rgb24,
2673                 int width,
2674                 int height) {
2675   return NV21ToRGB24Matrix(src_y, src_stride_y, src_vu, src_stride_vu,
2676                            dst_rgb24, dst_stride_rgb24, &kYuvI601Constants,
2677                            width, height);
2678 }
2679 
2680 // Convert NV12 to RAW.
2681 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)2682 int NV12ToRAW(const uint8_t* src_y,
2683               int src_stride_y,
2684               const uint8_t* src_uv,
2685               int src_stride_uv,
2686               uint8_t* dst_raw,
2687               int dst_stride_raw,
2688               int width,
2689               int height) {
2690   return NV21ToRGB24Matrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_raw,
2691                            dst_stride_raw, &kYvuI601Constants, width, height);
2692 }
2693 
2694 // Convert NV21 to RAW.
2695 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)2696 int NV21ToRAW(const uint8_t* src_y,
2697               int src_stride_y,
2698               const uint8_t* src_vu,
2699               int src_stride_vu,
2700               uint8_t* dst_raw,
2701               int dst_stride_raw,
2702               int width,
2703               int height) {
2704   return NV12ToRGB24Matrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_raw,
2705                            dst_stride_raw, &kYvuI601Constants, width, height);
2706 }
2707 
2708 // 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)2709 int NV21ToYUV24(const uint8_t* src_y,
2710                 int src_stride_y,
2711                 const uint8_t* src_vu,
2712                 int src_stride_vu,
2713                 uint8_t* dst_yuv24,
2714                 int dst_stride_yuv24,
2715                 int width,
2716                 int height) {
2717   int y;
2718   void (*NV21ToYUV24Row)(const uint8_t* src_y, const uint8_t* src_vu,
2719                          uint8_t* dst_yuv24, int width) = NV21ToYUV24Row_C;
2720   if (!src_y || !src_vu || !dst_yuv24 || width <= 0 || height == 0) {
2721     return -1;
2722   }
2723   // Negative height means invert the image.
2724   if (height < 0) {
2725     height = -height;
2726     dst_yuv24 = dst_yuv24 + (height - 1) * dst_stride_yuv24;
2727     dst_stride_yuv24 = -dst_stride_yuv24;
2728   }
2729 #if defined(HAS_NV21TOYUV24ROW_NEON)
2730   if (TestCpuFlag(kCpuHasNEON)) {
2731     NV21ToYUV24Row = NV21ToYUV24Row_Any_NEON;
2732     if (IS_ALIGNED(width, 16)) {
2733       NV21ToYUV24Row = NV21ToYUV24Row_NEON;
2734     }
2735   }
2736 #endif
2737 #if defined(HAS_NV21TOYUV24ROW_AVX2)
2738   if (TestCpuFlag(kCpuHasAVX2)) {
2739     NV21ToYUV24Row = NV21ToYUV24Row_Any_AVX2;
2740     if (IS_ALIGNED(width, 32)) {
2741       NV21ToYUV24Row = NV21ToYUV24Row_AVX2;
2742     }
2743   }
2744 #endif
2745   for (y = 0; y < height; ++y) {
2746     NV21ToYUV24Row(src_y, src_vu, dst_yuv24, width);
2747     dst_yuv24 += dst_stride_yuv24;
2748     src_y += src_stride_y;
2749     if (y & 1) {
2750       src_vu += src_stride_vu;
2751     }
2752   }
2753   return 0;
2754 }
2755 
2756 // Convert YUY2 to ARGB.
2757 LIBYUV_API
YUY2ToARGB(const uint8_t * src_yuy2,int src_stride_yuy2,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2758 int YUY2ToARGB(const uint8_t* src_yuy2,
2759                int src_stride_yuy2,
2760                uint8_t* dst_argb,
2761                int dst_stride_argb,
2762                int width,
2763                int height) {
2764   int y;
2765   void (*YUY2ToARGBRow)(const uint8_t* src_yuy2, uint8_t* dst_argb,
2766                         const struct YuvConstants* yuvconstants, int width) =
2767       YUY2ToARGBRow_C;
2768   if (!src_yuy2 || !dst_argb || width <= 0 || height == 0) {
2769     return -1;
2770   }
2771   // Negative height means invert the image.
2772   if (height < 0) {
2773     height = -height;
2774     src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
2775     src_stride_yuy2 = -src_stride_yuy2;
2776   }
2777   // Coalesce rows.
2778   if (src_stride_yuy2 == width * 2 && dst_stride_argb == width * 4) {
2779     width *= height;
2780     height = 1;
2781     src_stride_yuy2 = dst_stride_argb = 0;
2782   }
2783 #if defined(HAS_YUY2TOARGBROW_SSSE3)
2784   if (TestCpuFlag(kCpuHasSSSE3)) {
2785     YUY2ToARGBRow = YUY2ToARGBRow_Any_SSSE3;
2786     if (IS_ALIGNED(width, 16)) {
2787       YUY2ToARGBRow = YUY2ToARGBRow_SSSE3;
2788     }
2789   }
2790 #endif
2791 #if defined(HAS_YUY2TOARGBROW_AVX2)
2792   if (TestCpuFlag(kCpuHasAVX2)) {
2793     YUY2ToARGBRow = YUY2ToARGBRow_Any_AVX2;
2794     if (IS_ALIGNED(width, 32)) {
2795       YUY2ToARGBRow = YUY2ToARGBRow_AVX2;
2796     }
2797   }
2798 #endif
2799 #if defined(HAS_YUY2TOARGBROW_NEON)
2800   if (TestCpuFlag(kCpuHasNEON)) {
2801     YUY2ToARGBRow = YUY2ToARGBRow_Any_NEON;
2802     if (IS_ALIGNED(width, 8)) {
2803       YUY2ToARGBRow = YUY2ToARGBRow_NEON;
2804     }
2805   }
2806 #endif
2807 #if defined(HAS_YUY2TOARGBROW_MMI)
2808   if (TestCpuFlag(kCpuHasMMI)) {
2809     YUY2ToARGBRow = YUY2ToARGBRow_Any_MMI;
2810     if (IS_ALIGNED(width, 4)) {
2811       YUY2ToARGBRow = YUY2ToARGBRow_MMI;
2812     }
2813   }
2814 #endif
2815 #if defined(HAS_YUY2TOARGBROW_MSA)
2816   if (TestCpuFlag(kCpuHasMSA)) {
2817     YUY2ToARGBRow = YUY2ToARGBRow_Any_MSA;
2818     if (IS_ALIGNED(width, 8)) {
2819       YUY2ToARGBRow = YUY2ToARGBRow_MSA;
2820     }
2821   }
2822 #endif
2823   for (y = 0; y < height; ++y) {
2824     YUY2ToARGBRow(src_yuy2, dst_argb, &kYuvI601Constants, width);
2825     src_yuy2 += src_stride_yuy2;
2826     dst_argb += dst_stride_argb;
2827   }
2828   return 0;
2829 }
2830 
2831 // Convert UYVY to ARGB.
2832 LIBYUV_API
UYVYToARGB(const uint8_t * src_uyvy,int src_stride_uyvy,uint8_t * dst_argb,int dst_stride_argb,int width,int height)2833 int UYVYToARGB(const uint8_t* src_uyvy,
2834                int src_stride_uyvy,
2835                uint8_t* dst_argb,
2836                int dst_stride_argb,
2837                int width,
2838                int height) {
2839   int y;
2840   void (*UYVYToARGBRow)(const uint8_t* src_uyvy, uint8_t* dst_argb,
2841                         const struct YuvConstants* yuvconstants, int width) =
2842       UYVYToARGBRow_C;
2843   if (!src_uyvy || !dst_argb || width <= 0 || height == 0) {
2844     return -1;
2845   }
2846   // Negative height means invert the image.
2847   if (height < 0) {
2848     height = -height;
2849     src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
2850     src_stride_uyvy = -src_stride_uyvy;
2851   }
2852   // Coalesce rows.
2853   if (src_stride_uyvy == width * 2 && dst_stride_argb == width * 4) {
2854     width *= height;
2855     height = 1;
2856     src_stride_uyvy = dst_stride_argb = 0;
2857   }
2858 #if defined(HAS_UYVYTOARGBROW_SSSE3)
2859   if (TestCpuFlag(kCpuHasSSSE3)) {
2860     UYVYToARGBRow = UYVYToARGBRow_Any_SSSE3;
2861     if (IS_ALIGNED(width, 16)) {
2862       UYVYToARGBRow = UYVYToARGBRow_SSSE3;
2863     }
2864   }
2865 #endif
2866 #if defined(HAS_UYVYTOARGBROW_AVX2)
2867   if (TestCpuFlag(kCpuHasAVX2)) {
2868     UYVYToARGBRow = UYVYToARGBRow_Any_AVX2;
2869     if (IS_ALIGNED(width, 32)) {
2870       UYVYToARGBRow = UYVYToARGBRow_AVX2;
2871     }
2872   }
2873 #endif
2874 #if defined(HAS_UYVYTOARGBROW_NEON)
2875   if (TestCpuFlag(kCpuHasNEON)) {
2876     UYVYToARGBRow = UYVYToARGBRow_Any_NEON;
2877     if (IS_ALIGNED(width, 8)) {
2878       UYVYToARGBRow = UYVYToARGBRow_NEON;
2879     }
2880   }
2881 #endif
2882 #if defined(HAS_UYVYTOARGBROW_MMI)
2883   if (TestCpuFlag(kCpuHasMMI)) {
2884     UYVYToARGBRow = UYVYToARGBRow_Any_MMI;
2885     if (IS_ALIGNED(width, 4)) {
2886       UYVYToARGBRow = UYVYToARGBRow_MMI;
2887     }
2888   }
2889 #endif
2890 #if defined(HAS_UYVYTOARGBROW_MSA)
2891   if (TestCpuFlag(kCpuHasMSA)) {
2892     UYVYToARGBRow = UYVYToARGBRow_Any_MSA;
2893     if (IS_ALIGNED(width, 8)) {
2894       UYVYToARGBRow = UYVYToARGBRow_MSA;
2895     }
2896   }
2897 #endif
2898   for (y = 0; y < height; ++y) {
2899     UYVYToARGBRow(src_uyvy, dst_argb, &kYuvI601Constants, width);
2900     src_uyvy += src_stride_uyvy;
2901     dst_argb += dst_stride_argb;
2902   }
2903   return 0;
2904 }
WeavePixels(const uint8_t * src_u,const uint8_t * src_v,int src_pixel_stride_uv,uint8_t * dst_uv,int width)2905 static void WeavePixels(const uint8_t* src_u,
2906                         const uint8_t* src_v,
2907                         int src_pixel_stride_uv,
2908                         uint8_t* dst_uv,
2909                         int width) {
2910   int i;
2911   for (i = 0; i < width; ++i) {
2912     dst_uv[0] = *src_u;
2913     dst_uv[1] = *src_v;
2914     dst_uv += 2;
2915     src_u += src_pixel_stride_uv;
2916     src_v += src_pixel_stride_uv;
2917   }
2918 }
2919 
2920 // Convert Android420 to ARGB with matrix.
2921 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)2922 int Android420ToARGBMatrix(const uint8_t* src_y,
2923                            int src_stride_y,
2924                            const uint8_t* src_u,
2925                            int src_stride_u,
2926                            const uint8_t* src_v,
2927                            int src_stride_v,
2928                            int src_pixel_stride_uv,
2929                            uint8_t* dst_argb,
2930                            int dst_stride_argb,
2931                            const struct YuvConstants* yuvconstants,
2932                            int width,
2933                            int height) {
2934   int y;
2935   uint8_t* dst_uv;
2936   const ptrdiff_t vu_off = src_v - src_u;
2937   int halfwidth = (width + 1) >> 1;
2938   int halfheight = (height + 1) >> 1;
2939   if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) {
2940     return -1;
2941   }
2942   // Negative height means invert the image.
2943   if (height < 0) {
2944     height = -height;
2945     halfheight = (height + 1) >> 1;
2946     dst_argb = dst_argb + (height - 1) * dst_stride_argb;
2947     dst_stride_argb = -dst_stride_argb;
2948   }
2949 
2950   // I420
2951   if (src_pixel_stride_uv == 1) {
2952     return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
2953                             src_stride_v, dst_argb, dst_stride_argb,
2954                             yuvconstants, width, height);
2955     // NV21
2956   }
2957   if (src_pixel_stride_uv == 2 && vu_off == -1 &&
2958       src_stride_u == src_stride_v) {
2959     return NV21ToARGBMatrix(src_y, src_stride_y, src_v, src_stride_v, dst_argb,
2960                             dst_stride_argb, yuvconstants, width, height);
2961     // NV12
2962   }
2963   if (src_pixel_stride_uv == 2 && vu_off == 1 && src_stride_u == src_stride_v) {
2964     return NV12ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, dst_argb,
2965                             dst_stride_argb, yuvconstants, width, height);
2966   }
2967 
2968   // General case fallback creates NV12
2969   align_buffer_64(plane_uv, halfwidth * 2 * halfheight);
2970   dst_uv = plane_uv;
2971   for (y = 0; y < halfheight; ++y) {
2972     WeavePixels(src_u, src_v, src_pixel_stride_uv, dst_uv, halfwidth);
2973     src_u += src_stride_u;
2974     src_v += src_stride_v;
2975     dst_uv += halfwidth * 2;
2976   }
2977   NV12ToARGBMatrix(src_y, src_stride_y, plane_uv, halfwidth * 2, dst_argb,
2978                    dst_stride_argb, yuvconstants, width, height);
2979   free_aligned_buffer_64(plane_uv);
2980   return 0;
2981 }
2982 
2983 // Convert Android420 to ARGB.
2984 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)2985 int Android420ToARGB(const uint8_t* src_y,
2986                      int src_stride_y,
2987                      const uint8_t* src_u,
2988                      int src_stride_u,
2989                      const uint8_t* src_v,
2990                      int src_stride_v,
2991                      int src_pixel_stride_uv,
2992                      uint8_t* dst_argb,
2993                      int dst_stride_argb,
2994                      int width,
2995                      int height) {
2996   return Android420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
2997                                 src_stride_v, src_pixel_stride_uv, dst_argb,
2998                                 dst_stride_argb, &kYuvI601Constants, width,
2999                                 height);
3000 }
3001 
3002 // Convert Android420 to ABGR.
3003 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)3004 int Android420ToABGR(const uint8_t* src_y,
3005                      int src_stride_y,
3006                      const uint8_t* src_u,
3007                      int src_stride_u,
3008                      const uint8_t* src_v,
3009                      int src_stride_v,
3010                      int src_pixel_stride_uv,
3011                      uint8_t* dst_abgr,
3012                      int dst_stride_abgr,
3013                      int width,
3014                      int height) {
3015   return Android420ToARGBMatrix(src_y, src_stride_y, src_v, src_stride_v, src_u,
3016                                 src_stride_u, src_pixel_stride_uv, dst_abgr,
3017                                 dst_stride_abgr, &kYvuI601Constants, width,
3018                                 height);
3019 }
3020 
3021 // Convert I422 to RGBA with matrix.
3022 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)3023 int I422ToRGBAMatrix(const uint8_t* src_y,
3024                      int src_stride_y,
3025                      const uint8_t* src_u,
3026                      int src_stride_u,
3027                      const uint8_t* src_v,
3028                      int src_stride_v,
3029                      uint8_t* dst_rgba,
3030                      int dst_stride_rgba,
3031                      const struct YuvConstants* yuvconstants,
3032                      int width,
3033                      int height) {
3034   int y;
3035   void (*I422ToRGBARow)(const uint8_t* y_buf, const uint8_t* u_buf,
3036                         const uint8_t* v_buf, uint8_t* rgb_buf,
3037                         const struct YuvConstants* yuvconstants, int width) =
3038       I422ToRGBARow_C;
3039   if (!src_y || !src_u || !src_v || !dst_rgba || width <= 0 || height == 0) {
3040     return -1;
3041   }
3042   // Negative height means invert the image.
3043   if (height < 0) {
3044     height = -height;
3045     dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba;
3046     dst_stride_rgba = -dst_stride_rgba;
3047   }
3048 #if defined(HAS_I422TORGBAROW_SSSE3)
3049   if (TestCpuFlag(kCpuHasSSSE3)) {
3050     I422ToRGBARow = I422ToRGBARow_Any_SSSE3;
3051     if (IS_ALIGNED(width, 8)) {
3052       I422ToRGBARow = I422ToRGBARow_SSSE3;
3053     }
3054   }
3055 #endif
3056 #if defined(HAS_I422TORGBAROW_AVX2)
3057   if (TestCpuFlag(kCpuHasAVX2)) {
3058     I422ToRGBARow = I422ToRGBARow_Any_AVX2;
3059     if (IS_ALIGNED(width, 16)) {
3060       I422ToRGBARow = I422ToRGBARow_AVX2;
3061     }
3062   }
3063 #endif
3064 #if defined(HAS_I422TORGBAROW_NEON)
3065   if (TestCpuFlag(kCpuHasNEON)) {
3066     I422ToRGBARow = I422ToRGBARow_Any_NEON;
3067     if (IS_ALIGNED(width, 8)) {
3068       I422ToRGBARow = I422ToRGBARow_NEON;
3069     }
3070   }
3071 #endif
3072 #if defined(HAS_I422TORGBAROW_MMI)
3073   if (TestCpuFlag(kCpuHasMMI)) {
3074     I422ToRGBARow = I422ToRGBARow_Any_MMI;
3075     if (IS_ALIGNED(width, 4)) {
3076       I422ToRGBARow = I422ToRGBARow_MMI;
3077     }
3078   }
3079 #endif
3080 #if defined(HAS_I422TORGBAROW_MSA)
3081   if (TestCpuFlag(kCpuHasMSA)) {
3082     I422ToRGBARow = I422ToRGBARow_Any_MSA;
3083     if (IS_ALIGNED(width, 8)) {
3084       I422ToRGBARow = I422ToRGBARow_MSA;
3085     }
3086   }
3087 #endif
3088 
3089   for (y = 0; y < height; ++y) {
3090     I422ToRGBARow(src_y, src_u, src_v, dst_rgba, yuvconstants, width);
3091     dst_rgba += dst_stride_rgba;
3092     src_y += src_stride_y;
3093     src_u += src_stride_u;
3094     src_v += src_stride_v;
3095   }
3096   return 0;
3097 }
3098 
3099 // Convert I422 to RGBA.
3100 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)3101 int I422ToRGBA(const uint8_t* src_y,
3102                int src_stride_y,
3103                const uint8_t* src_u,
3104                int src_stride_u,
3105                const uint8_t* src_v,
3106                int src_stride_v,
3107                uint8_t* dst_rgba,
3108                int dst_stride_rgba,
3109                int width,
3110                int height) {
3111   return I422ToRGBAMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
3112                           src_stride_v, dst_rgba, dst_stride_rgba,
3113                           &kYuvI601Constants, width, height);
3114 }
3115 
3116 // Convert I422 to BGRA.
3117 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)3118 int I422ToBGRA(const uint8_t* src_y,
3119                int src_stride_y,
3120                const uint8_t* src_u,
3121                int src_stride_u,
3122                const uint8_t* src_v,
3123                int src_stride_v,
3124                uint8_t* dst_bgra,
3125                int dst_stride_bgra,
3126                int width,
3127                int height) {
3128   return I422ToRGBAMatrix(src_y, src_stride_y, src_v,
3129                           src_stride_v,  // Swap U and V
3130                           src_u, src_stride_u, dst_bgra, dst_stride_bgra,
3131                           &kYvuI601Constants,  // Use Yvu matrix
3132                           width, height);
3133 }
3134 
3135 // Convert NV12 to RGB565 with matrix.
3136 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)3137 int NV12ToRGB565Matrix(const uint8_t* src_y,
3138                        int src_stride_y,
3139                        const uint8_t* src_uv,
3140                        int src_stride_uv,
3141                        uint8_t* dst_rgb565,
3142                        int dst_stride_rgb565,
3143                        const struct YuvConstants* yuvconstants,
3144                        int width,
3145                        int height) {
3146   int y;
3147   void (*NV12ToRGB565Row)(
3148       const uint8_t* y_buf, const uint8_t* uv_buf, uint8_t* rgb_buf,
3149       const struct YuvConstants* yuvconstants, int width) = NV12ToRGB565Row_C;
3150   if (!src_y || !src_uv || !dst_rgb565 || width <= 0 || height == 0) {
3151     return -1;
3152   }
3153   // Negative height means invert the image.
3154   if (height < 0) {
3155     height = -height;
3156     dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
3157     dst_stride_rgb565 = -dst_stride_rgb565;
3158   }
3159 #if defined(HAS_NV12TORGB565ROW_SSSE3)
3160   if (TestCpuFlag(kCpuHasSSSE3)) {
3161     NV12ToRGB565Row = NV12ToRGB565Row_Any_SSSE3;
3162     if (IS_ALIGNED(width, 8)) {
3163       NV12ToRGB565Row = NV12ToRGB565Row_SSSE3;
3164     }
3165   }
3166 #endif
3167 #if defined(HAS_NV12TORGB565ROW_AVX2)
3168   if (TestCpuFlag(kCpuHasAVX2)) {
3169     NV12ToRGB565Row = NV12ToRGB565Row_Any_AVX2;
3170     if (IS_ALIGNED(width, 16)) {
3171       NV12ToRGB565Row = NV12ToRGB565Row_AVX2;
3172     }
3173   }
3174 #endif
3175 #if defined(HAS_NV12TORGB565ROW_NEON)
3176   if (TestCpuFlag(kCpuHasNEON)) {
3177     NV12ToRGB565Row = NV12ToRGB565Row_Any_NEON;
3178     if (IS_ALIGNED(width, 8)) {
3179       NV12ToRGB565Row = NV12ToRGB565Row_NEON;
3180     }
3181   }
3182 #endif
3183 #if defined(HAS_NV12TORGB565ROW_MMI)
3184   if (TestCpuFlag(kCpuHasMMI)) {
3185     NV12ToRGB565Row = NV12ToRGB565Row_Any_MMI;
3186     if (IS_ALIGNED(width, 4)) {
3187       NV12ToRGB565Row = NV12ToRGB565Row_MMI;
3188     }
3189   }
3190 #endif
3191 #if defined(HAS_NV12TORGB565ROW_MSA)
3192   if (TestCpuFlag(kCpuHasMSA)) {
3193     NV12ToRGB565Row = NV12ToRGB565Row_Any_MSA;
3194     if (IS_ALIGNED(width, 8)) {
3195       NV12ToRGB565Row = NV12ToRGB565Row_MSA;
3196     }
3197   }
3198 #endif
3199 
3200   for (y = 0; y < height; ++y) {
3201     NV12ToRGB565Row(src_y, src_uv, dst_rgb565, yuvconstants, width);
3202     dst_rgb565 += dst_stride_rgb565;
3203     src_y += src_stride_y;
3204     if (y & 1) {
3205       src_uv += src_stride_uv;
3206     }
3207   }
3208   return 0;
3209 }
3210 
3211 // Convert NV12 to RGB565.
3212 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)3213 int NV12ToRGB565(const uint8_t* src_y,
3214                  int src_stride_y,
3215                  const uint8_t* src_uv,
3216                  int src_stride_uv,
3217                  uint8_t* dst_rgb565,
3218                  int dst_stride_rgb565,
3219                  int width,
3220                  int height) {
3221   return NV12ToRGB565Matrix(src_y, src_stride_y, src_uv, src_stride_uv,
3222                             dst_rgb565, dst_stride_rgb565, &kYuvI601Constants,
3223                             width, height);
3224 }
3225 
3226 // Convert I422 to RGBA with matrix.
3227 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)3228 int I420ToRGBAMatrix(const uint8_t* src_y,
3229                      int src_stride_y,
3230                      const uint8_t* src_u,
3231                      int src_stride_u,
3232                      const uint8_t* src_v,
3233                      int src_stride_v,
3234                      uint8_t* dst_rgba,
3235                      int dst_stride_rgba,
3236                      const struct YuvConstants* yuvconstants,
3237                      int width,
3238                      int height) {
3239   int y;
3240   void (*I422ToRGBARow)(const uint8_t* y_buf, const uint8_t* u_buf,
3241                         const uint8_t* v_buf, uint8_t* rgb_buf,
3242                         const struct YuvConstants* yuvconstants, int width) =
3243       I422ToRGBARow_C;
3244   if (!src_y || !src_u || !src_v || !dst_rgba || width <= 0 || height == 0) {
3245     return -1;
3246   }
3247   // Negative height means invert the image.
3248   if (height < 0) {
3249     height = -height;
3250     dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba;
3251     dst_stride_rgba = -dst_stride_rgba;
3252   }
3253 #if defined(HAS_I422TORGBAROW_SSSE3)
3254   if (TestCpuFlag(kCpuHasSSSE3)) {
3255     I422ToRGBARow = I422ToRGBARow_Any_SSSE3;
3256     if (IS_ALIGNED(width, 8)) {
3257       I422ToRGBARow = I422ToRGBARow_SSSE3;
3258     }
3259   }
3260 #endif
3261 #if defined(HAS_I422TORGBAROW_AVX2)
3262   if (TestCpuFlag(kCpuHasAVX2)) {
3263     I422ToRGBARow = I422ToRGBARow_Any_AVX2;
3264     if (IS_ALIGNED(width, 16)) {
3265       I422ToRGBARow = I422ToRGBARow_AVX2;
3266     }
3267   }
3268 #endif
3269 #if defined(HAS_I422TORGBAROW_NEON)
3270   if (TestCpuFlag(kCpuHasNEON)) {
3271     I422ToRGBARow = I422ToRGBARow_Any_NEON;
3272     if (IS_ALIGNED(width, 8)) {
3273       I422ToRGBARow = I422ToRGBARow_NEON;
3274     }
3275   }
3276 #endif
3277 #if defined(HAS_I422TORGBAROW_MMI)
3278   if (TestCpuFlag(kCpuHasMMI)) {
3279     I422ToRGBARow = I422ToRGBARow_Any_MMI;
3280     if (IS_ALIGNED(width, 4)) {
3281       I422ToRGBARow = I422ToRGBARow_MMI;
3282     }
3283   }
3284 #endif
3285 #if defined(HAS_I422TORGBAROW_MSA)
3286   if (TestCpuFlag(kCpuHasMSA)) {
3287     I422ToRGBARow = I422ToRGBARow_Any_MSA;
3288     if (IS_ALIGNED(width, 8)) {
3289       I422ToRGBARow = I422ToRGBARow_MSA;
3290     }
3291   }
3292 #endif
3293 
3294   for (y = 0; y < height; ++y) {
3295     I422ToRGBARow(src_y, src_u, src_v, dst_rgba, yuvconstants, width);
3296     dst_rgba += dst_stride_rgba;
3297     src_y += src_stride_y;
3298     if (y & 1) {
3299       src_u += src_stride_u;
3300       src_v += src_stride_v;
3301     }
3302   }
3303   return 0;
3304 }
3305 
3306 // Convert I420 to RGBA.
3307 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)3308 int I420ToRGBA(const uint8_t* src_y,
3309                int src_stride_y,
3310                const uint8_t* src_u,
3311                int src_stride_u,
3312                const uint8_t* src_v,
3313                int src_stride_v,
3314                uint8_t* dst_rgba,
3315                int dst_stride_rgba,
3316                int width,
3317                int height) {
3318   return I420ToRGBAMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
3319                           src_stride_v, dst_rgba, dst_stride_rgba,
3320                           &kYuvI601Constants, width, height);
3321 }
3322 
3323 // Convert I420 to BGRA.
3324 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)3325 int I420ToBGRA(const uint8_t* src_y,
3326                int src_stride_y,
3327                const uint8_t* src_u,
3328                int src_stride_u,
3329                const uint8_t* src_v,
3330                int src_stride_v,
3331                uint8_t* dst_bgra,
3332                int dst_stride_bgra,
3333                int width,
3334                int height) {
3335   return I420ToRGBAMatrix(src_y, src_stride_y, src_v,
3336                           src_stride_v,  // Swap U and V
3337                           src_u, src_stride_u, dst_bgra, dst_stride_bgra,
3338                           &kYvuI601Constants,  // Use Yvu matrix
3339                           width, height);
3340 }
3341 
3342 // Convert I420 to RGB24 with matrix.
3343 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)3344 int I420ToRGB24Matrix(const uint8_t* src_y,
3345                       int src_stride_y,
3346                       const uint8_t* src_u,
3347                       int src_stride_u,
3348                       const uint8_t* src_v,
3349                       int src_stride_v,
3350                       uint8_t* dst_rgb24,
3351                       int dst_stride_rgb24,
3352                       const struct YuvConstants* yuvconstants,
3353                       int width,
3354                       int height) {
3355   int y;
3356   void (*I422ToRGB24Row)(const uint8_t* y_buf, const uint8_t* u_buf,
3357                          const uint8_t* v_buf, uint8_t* rgb_buf,
3358                          const struct YuvConstants* yuvconstants, int width) =
3359       I422ToRGB24Row_C;
3360   if (!src_y || !src_u || !src_v || !dst_rgb24 || width <= 0 || height == 0) {
3361     return -1;
3362   }
3363   // Negative height means invert the image.
3364   if (height < 0) {
3365     height = -height;
3366     dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24;
3367     dst_stride_rgb24 = -dst_stride_rgb24;
3368   }
3369 #if defined(HAS_I422TORGB24ROW_SSSE3)
3370   if (TestCpuFlag(kCpuHasSSSE3)) {
3371     I422ToRGB24Row = I422ToRGB24Row_Any_SSSE3;
3372     if (IS_ALIGNED(width, 16)) {
3373       I422ToRGB24Row = I422ToRGB24Row_SSSE3;
3374     }
3375   }
3376 #endif
3377 #if defined(HAS_I422TORGB24ROW_AVX2)
3378   if (TestCpuFlag(kCpuHasAVX2)) {
3379     I422ToRGB24Row = I422ToRGB24Row_Any_AVX2;
3380     if (IS_ALIGNED(width, 32)) {
3381       I422ToRGB24Row = I422ToRGB24Row_AVX2;
3382     }
3383   }
3384 #endif
3385 #if defined(HAS_I422TORGB24ROW_NEON)
3386   if (TestCpuFlag(kCpuHasNEON)) {
3387     I422ToRGB24Row = I422ToRGB24Row_Any_NEON;
3388     if (IS_ALIGNED(width, 8)) {
3389       I422ToRGB24Row = I422ToRGB24Row_NEON;
3390     }
3391   }
3392 #endif
3393 #if defined(HAS_I422TORGB24ROW_MMI)
3394   if (TestCpuFlag(kCpuHasMMI)) {
3395     I422ToRGB24Row = I422ToRGB24Row_Any_MMI;
3396     if (IS_ALIGNED(width, 4)) {
3397       I422ToRGB24Row = I422ToRGB24Row_MMI;
3398     }
3399   }
3400 #endif
3401 #if defined(HAS_I422TORGB24ROW_MSA)
3402   if (TestCpuFlag(kCpuHasMSA)) {
3403     I422ToRGB24Row = I422ToRGB24Row_Any_MSA;
3404     if (IS_ALIGNED(width, 16)) {
3405       I422ToRGB24Row = I422ToRGB24Row_MSA;
3406     }
3407   }
3408 #endif
3409 
3410   for (y = 0; y < height; ++y) {
3411     I422ToRGB24Row(src_y, src_u, src_v, dst_rgb24, yuvconstants, width);
3412     dst_rgb24 += dst_stride_rgb24;
3413     src_y += src_stride_y;
3414     if (y & 1) {
3415       src_u += src_stride_u;
3416       src_v += src_stride_v;
3417     }
3418   }
3419   return 0;
3420 }
3421 
3422 // Convert I420 to RGB24.
3423 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)3424 int I420ToRGB24(const uint8_t* src_y,
3425                 int src_stride_y,
3426                 const uint8_t* src_u,
3427                 int src_stride_u,
3428                 const uint8_t* src_v,
3429                 int src_stride_v,
3430                 uint8_t* dst_rgb24,
3431                 int dst_stride_rgb24,
3432                 int width,
3433                 int height) {
3434   return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
3435                            src_stride_v, dst_rgb24, dst_stride_rgb24,
3436                            &kYuvI601Constants, width, height);
3437 }
3438 
3439 // Convert I420 to RAW.
3440 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)3441 int I420ToRAW(const uint8_t* src_y,
3442               int src_stride_y,
3443               const uint8_t* src_u,
3444               int src_stride_u,
3445               const uint8_t* src_v,
3446               int src_stride_v,
3447               uint8_t* dst_raw,
3448               int dst_stride_raw,
3449               int width,
3450               int height) {
3451   return I420ToRGB24Matrix(src_y, src_stride_y, src_v,
3452                            src_stride_v,  // Swap U and V
3453                            src_u, src_stride_u, dst_raw, dst_stride_raw,
3454                            &kYvuI601Constants,  // Use Yvu matrix
3455                            width, height);
3456 }
3457 
3458 // Convert J420 to RGB24.
3459 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)3460 int J420ToRGB24(const uint8_t* src_y,
3461                 int src_stride_y,
3462                 const uint8_t* src_u,
3463                 int src_stride_u,
3464                 const uint8_t* src_v,
3465                 int src_stride_v,
3466                 uint8_t* dst_rgb24,
3467                 int dst_stride_rgb24,
3468                 int width,
3469                 int height) {
3470   return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
3471                            src_stride_v, dst_rgb24, dst_stride_rgb24,
3472                            &kYuvJPEGConstants, width, height);
3473 }
3474 
3475 // Convert J420 to RAW.
3476 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)3477 int J420ToRAW(const uint8_t* src_y,
3478               int src_stride_y,
3479               const uint8_t* src_u,
3480               int src_stride_u,
3481               const uint8_t* src_v,
3482               int src_stride_v,
3483               uint8_t* dst_raw,
3484               int dst_stride_raw,
3485               int width,
3486               int height) {
3487   return I420ToRGB24Matrix(src_y, src_stride_y, src_v,
3488                            src_stride_v,  // Swap U and V
3489                            src_u, src_stride_u, dst_raw, dst_stride_raw,
3490                            &kYvuJPEGConstants,  // Use Yvu matrix
3491                            width, height);
3492 }
3493 
3494 // Convert H420 to RGB24.
3495 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)3496 int H420ToRGB24(const uint8_t* src_y,
3497                 int src_stride_y,
3498                 const uint8_t* src_u,
3499                 int src_stride_u,
3500                 const uint8_t* src_v,
3501                 int src_stride_v,
3502                 uint8_t* dst_rgb24,
3503                 int dst_stride_rgb24,
3504                 int width,
3505                 int height) {
3506   return I420ToRGB24Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
3507                            src_stride_v, dst_rgb24, dst_stride_rgb24,
3508                            &kYuvH709Constants, width, height);
3509 }
3510 
3511 // Convert H420 to RAW.
3512 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)3513 int H420ToRAW(const uint8_t* src_y,
3514               int src_stride_y,
3515               const uint8_t* src_u,
3516               int src_stride_u,
3517               const uint8_t* src_v,
3518               int src_stride_v,
3519               uint8_t* dst_raw,
3520               int dst_stride_raw,
3521               int width,
3522               int height) {
3523   return I420ToRGB24Matrix(src_y, src_stride_y, src_v,
3524                            src_stride_v,  // Swap U and V
3525                            src_u, src_stride_u, dst_raw, dst_stride_raw,
3526                            &kYvuH709Constants,  // Use Yvu matrix
3527                            width, height);
3528 }
3529 
3530 // Convert I420 to ARGB1555.
3531 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)3532 int I420ToARGB1555(const uint8_t* src_y,
3533                    int src_stride_y,
3534                    const uint8_t* src_u,
3535                    int src_stride_u,
3536                    const uint8_t* src_v,
3537                    int src_stride_v,
3538                    uint8_t* dst_argb1555,
3539                    int dst_stride_argb1555,
3540                    int width,
3541                    int height) {
3542   int y;
3543   void (*I422ToARGB1555Row)(const uint8_t* y_buf, const uint8_t* u_buf,
3544                             const uint8_t* v_buf, uint8_t* rgb_buf,
3545                             const struct YuvConstants* yuvconstants,
3546                             int width) = I422ToARGB1555Row_C;
3547   if (!src_y || !src_u || !src_v || !dst_argb1555 || width <= 0 ||
3548       height == 0) {
3549     return -1;
3550   }
3551   // Negative height means invert the image.
3552   if (height < 0) {
3553     height = -height;
3554     dst_argb1555 = dst_argb1555 + (height - 1) * dst_stride_argb1555;
3555     dst_stride_argb1555 = -dst_stride_argb1555;
3556   }
3557 #if defined(HAS_I422TOARGB1555ROW_SSSE3)
3558   if (TestCpuFlag(kCpuHasSSSE3)) {
3559     I422ToARGB1555Row = I422ToARGB1555Row_Any_SSSE3;
3560     if (IS_ALIGNED(width, 8)) {
3561       I422ToARGB1555Row = I422ToARGB1555Row_SSSE3;
3562     }
3563   }
3564 #endif
3565 #if defined(HAS_I422TOARGB1555ROW_AVX2)
3566   if (TestCpuFlag(kCpuHasAVX2)) {
3567     I422ToARGB1555Row = I422ToARGB1555Row_Any_AVX2;
3568     if (IS_ALIGNED(width, 16)) {
3569       I422ToARGB1555Row = I422ToARGB1555Row_AVX2;
3570     }
3571   }
3572 #endif
3573 #if defined(HAS_I422TOARGB1555ROW_NEON)
3574   if (TestCpuFlag(kCpuHasNEON)) {
3575     I422ToARGB1555Row = I422ToARGB1555Row_Any_NEON;
3576     if (IS_ALIGNED(width, 8)) {
3577       I422ToARGB1555Row = I422ToARGB1555Row_NEON;
3578     }
3579   }
3580 #endif
3581 #if defined(HAS_I422TOARGB1555ROW_MMI)
3582   if (TestCpuFlag(kCpuHasMMI)) {
3583     I422ToARGB1555Row = I422ToARGB1555Row_Any_MMI;
3584     if (IS_ALIGNED(width, 4)) {
3585       I422ToARGB1555Row = I422ToARGB1555Row_MMI;
3586     }
3587   }
3588 #endif
3589 #if defined(HAS_I422TOARGB1555ROW_MSA)
3590   if (TestCpuFlag(kCpuHasMSA)) {
3591     I422ToARGB1555Row = I422ToARGB1555Row_Any_MSA;
3592     if (IS_ALIGNED(width, 8)) {
3593       I422ToARGB1555Row = I422ToARGB1555Row_MSA;
3594     }
3595   }
3596 #endif
3597 
3598   for (y = 0; y < height; ++y) {
3599     I422ToARGB1555Row(src_y, src_u, src_v, dst_argb1555, &kYuvI601Constants,
3600                       width);
3601     dst_argb1555 += dst_stride_argb1555;
3602     src_y += src_stride_y;
3603     if (y & 1) {
3604       src_u += src_stride_u;
3605       src_v += src_stride_v;
3606     }
3607   }
3608   return 0;
3609 }
3610 
3611 // Convert I420 to ARGB4444.
3612 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)3613 int I420ToARGB4444(const uint8_t* src_y,
3614                    int src_stride_y,
3615                    const uint8_t* src_u,
3616                    int src_stride_u,
3617                    const uint8_t* src_v,
3618                    int src_stride_v,
3619                    uint8_t* dst_argb4444,
3620                    int dst_stride_argb4444,
3621                    int width,
3622                    int height) {
3623   int y;
3624   void (*I422ToARGB4444Row)(const uint8_t* y_buf, const uint8_t* u_buf,
3625                             const uint8_t* v_buf, uint8_t* rgb_buf,
3626                             const struct YuvConstants* yuvconstants,
3627                             int width) = I422ToARGB4444Row_C;
3628   if (!src_y || !src_u || !src_v || !dst_argb4444 || width <= 0 ||
3629       height == 0) {
3630     return -1;
3631   }
3632   // Negative height means invert the image.
3633   if (height < 0) {
3634     height = -height;
3635     dst_argb4444 = dst_argb4444 + (height - 1) * dst_stride_argb4444;
3636     dst_stride_argb4444 = -dst_stride_argb4444;
3637   }
3638 #if defined(HAS_I422TOARGB4444ROW_SSSE3)
3639   if (TestCpuFlag(kCpuHasSSSE3)) {
3640     I422ToARGB4444Row = I422ToARGB4444Row_Any_SSSE3;
3641     if (IS_ALIGNED(width, 8)) {
3642       I422ToARGB4444Row = I422ToARGB4444Row_SSSE3;
3643     }
3644   }
3645 #endif
3646 #if defined(HAS_I422TOARGB4444ROW_AVX2)
3647   if (TestCpuFlag(kCpuHasAVX2)) {
3648     I422ToARGB4444Row = I422ToARGB4444Row_Any_AVX2;
3649     if (IS_ALIGNED(width, 16)) {
3650       I422ToARGB4444Row = I422ToARGB4444Row_AVX2;
3651     }
3652   }
3653 #endif
3654 #if defined(HAS_I422TOARGB4444ROW_NEON)
3655   if (TestCpuFlag(kCpuHasNEON)) {
3656     I422ToARGB4444Row = I422ToARGB4444Row_Any_NEON;
3657     if (IS_ALIGNED(width, 8)) {
3658       I422ToARGB4444Row = I422ToARGB4444Row_NEON;
3659     }
3660   }
3661 #endif
3662 #if defined(HAS_I422TOARGB4444ROW_MMI)
3663   if (TestCpuFlag(kCpuHasMMI)) {
3664     I422ToARGB4444Row = I422ToARGB4444Row_Any_MMI;
3665     if (IS_ALIGNED(width, 4)) {
3666       I422ToARGB4444Row = I422ToARGB4444Row_MMI;
3667     }
3668   }
3669 #endif
3670 #if defined(HAS_I422TOARGB4444ROW_MSA)
3671   if (TestCpuFlag(kCpuHasMSA)) {
3672     I422ToARGB4444Row = I422ToARGB4444Row_Any_MSA;
3673     if (IS_ALIGNED(width, 8)) {
3674       I422ToARGB4444Row = I422ToARGB4444Row_MSA;
3675     }
3676   }
3677 #endif
3678 
3679   for (y = 0; y < height; ++y) {
3680     I422ToARGB4444Row(src_y, src_u, src_v, dst_argb4444, &kYuvI601Constants,
3681                       width);
3682     dst_argb4444 += dst_stride_argb4444;
3683     src_y += src_stride_y;
3684     if (y & 1) {
3685       src_u += src_stride_u;
3686       src_v += src_stride_v;
3687     }
3688   }
3689   return 0;
3690 }
3691 
3692 // Convert I420 to RGB565 with specified color matrix.
3693 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)3694 int I420ToRGB565Matrix(const uint8_t* src_y,
3695                        int src_stride_y,
3696                        const uint8_t* src_u,
3697                        int src_stride_u,
3698                        const uint8_t* src_v,
3699                        int src_stride_v,
3700                        uint8_t* dst_rgb565,
3701                        int dst_stride_rgb565,
3702                        const struct YuvConstants* yuvconstants,
3703                        int width,
3704                        int height) {
3705   int y;
3706   void (*I422ToRGB565Row)(const uint8_t* y_buf, const uint8_t* u_buf,
3707                           const uint8_t* v_buf, uint8_t* rgb_buf,
3708                           const struct YuvConstants* yuvconstants, int width) =
3709       I422ToRGB565Row_C;
3710   if (!src_y || !src_u || !src_v || !dst_rgb565 || width <= 0 || height == 0) {
3711     return -1;
3712   }
3713   // Negative height means invert the image.
3714   if (height < 0) {
3715     height = -height;
3716     dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
3717     dst_stride_rgb565 = -dst_stride_rgb565;
3718   }
3719 #if defined(HAS_I422TORGB565ROW_SSSE3)
3720   if (TestCpuFlag(kCpuHasSSSE3)) {
3721     I422ToRGB565Row = I422ToRGB565Row_Any_SSSE3;
3722     if (IS_ALIGNED(width, 8)) {
3723       I422ToRGB565Row = I422ToRGB565Row_SSSE3;
3724     }
3725   }
3726 #endif
3727 #if defined(HAS_I422TORGB565ROW_AVX2)
3728   if (TestCpuFlag(kCpuHasAVX2)) {
3729     I422ToRGB565Row = I422ToRGB565Row_Any_AVX2;
3730     if (IS_ALIGNED(width, 16)) {
3731       I422ToRGB565Row = I422ToRGB565Row_AVX2;
3732     }
3733   }
3734 #endif
3735 #if defined(HAS_I422TORGB565ROW_NEON)
3736   if (TestCpuFlag(kCpuHasNEON)) {
3737     I422ToRGB565Row = I422ToRGB565Row_Any_NEON;
3738     if (IS_ALIGNED(width, 8)) {
3739       I422ToRGB565Row = I422ToRGB565Row_NEON;
3740     }
3741   }
3742 #endif
3743 #if defined(HAS_I422TORGB565ROW_MMI)
3744   if (TestCpuFlag(kCpuHasMMI)) {
3745     I422ToRGB565Row = I422ToRGB565Row_Any_MMI;
3746     if (IS_ALIGNED(width, 4)) {
3747       I422ToRGB565Row = I422ToRGB565Row_MMI;
3748     }
3749   }
3750 #endif
3751 #if defined(HAS_I422TORGB565ROW_MSA)
3752   if (TestCpuFlag(kCpuHasMSA)) {
3753     I422ToRGB565Row = I422ToRGB565Row_Any_MSA;
3754     if (IS_ALIGNED(width, 8)) {
3755       I422ToRGB565Row = I422ToRGB565Row_MSA;
3756     }
3757   }
3758 #endif
3759 
3760   for (y = 0; y < height; ++y) {
3761     I422ToRGB565Row(src_y, src_u, src_v, dst_rgb565, yuvconstants, width);
3762     dst_rgb565 += dst_stride_rgb565;
3763     src_y += src_stride_y;
3764     if (y & 1) {
3765       src_u += src_stride_u;
3766       src_v += src_stride_v;
3767     }
3768   }
3769   return 0;
3770 }
3771 
3772 // Convert I420 to RGB565.
3773 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)3774 int I420ToRGB565(const uint8_t* src_y,
3775                  int src_stride_y,
3776                  const uint8_t* src_u,
3777                  int src_stride_u,
3778                  const uint8_t* src_v,
3779                  int src_stride_v,
3780                  uint8_t* dst_rgb565,
3781                  int dst_stride_rgb565,
3782                  int width,
3783                  int height) {
3784   return I420ToRGB565Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
3785                             src_stride_v, dst_rgb565, dst_stride_rgb565,
3786                             &kYuvI601Constants, width, height);
3787 }
3788 
3789 // Convert J420 to RGB565.
3790 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)3791 int J420ToRGB565(const uint8_t* src_y,
3792                  int src_stride_y,
3793                  const uint8_t* src_u,
3794                  int src_stride_u,
3795                  const uint8_t* src_v,
3796                  int src_stride_v,
3797                  uint8_t* dst_rgb565,
3798                  int dst_stride_rgb565,
3799                  int width,
3800                  int height) {
3801   return I420ToRGB565Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
3802                             src_stride_v, dst_rgb565, dst_stride_rgb565,
3803                             &kYuvJPEGConstants, width, height);
3804 }
3805 
3806 // Convert H420 to RGB565.
3807 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)3808 int H420ToRGB565(const uint8_t* src_y,
3809                  int src_stride_y,
3810                  const uint8_t* src_u,
3811                  int src_stride_u,
3812                  const uint8_t* src_v,
3813                  int src_stride_v,
3814                  uint8_t* dst_rgb565,
3815                  int dst_stride_rgb565,
3816                  int width,
3817                  int height) {
3818   return I420ToRGB565Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
3819                             src_stride_v, dst_rgb565, dst_stride_rgb565,
3820                             &kYuvH709Constants, width, height);
3821 }
3822 
3823 // Convert I422 to RGB565.
3824 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)3825 int I422ToRGB565(const uint8_t* src_y,
3826                  int src_stride_y,
3827                  const uint8_t* src_u,
3828                  int src_stride_u,
3829                  const uint8_t* src_v,
3830                  int src_stride_v,
3831                  uint8_t* dst_rgb565,
3832                  int dst_stride_rgb565,
3833                  int width,
3834                  int height) {
3835   int y;
3836   void (*I422ToRGB565Row)(const uint8_t* y_buf, const uint8_t* u_buf,
3837                           const uint8_t* v_buf, uint8_t* rgb_buf,
3838                           const struct YuvConstants* yuvconstants, int width) =
3839       I422ToRGB565Row_C;
3840   if (!src_y || !src_u || !src_v || !dst_rgb565 || width <= 0 || height == 0) {
3841     return -1;
3842   }
3843   // Negative height means invert the image.
3844   if (height < 0) {
3845     height = -height;
3846     dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
3847     dst_stride_rgb565 = -dst_stride_rgb565;
3848   }
3849 #if defined(HAS_I422TORGB565ROW_SSSE3)
3850   if (TestCpuFlag(kCpuHasSSSE3)) {
3851     I422ToRGB565Row = I422ToRGB565Row_Any_SSSE3;
3852     if (IS_ALIGNED(width, 8)) {
3853       I422ToRGB565Row = I422ToRGB565Row_SSSE3;
3854     }
3855   }
3856 #endif
3857 #if defined(HAS_I422TORGB565ROW_AVX2)
3858   if (TestCpuFlag(kCpuHasAVX2)) {
3859     I422ToRGB565Row = I422ToRGB565Row_Any_AVX2;
3860     if (IS_ALIGNED(width, 16)) {
3861       I422ToRGB565Row = I422ToRGB565Row_AVX2;
3862     }
3863   }
3864 #endif
3865 #if defined(HAS_I422TORGB565ROW_NEON)
3866   if (TestCpuFlag(kCpuHasNEON)) {
3867     I422ToRGB565Row = I422ToRGB565Row_Any_NEON;
3868     if (IS_ALIGNED(width, 8)) {
3869       I422ToRGB565Row = I422ToRGB565Row_NEON;
3870     }
3871   }
3872 #endif
3873 #if defined(HAS_I422TORGB565ROW_MSA)
3874   if (TestCpuFlag(kCpuHasMSA)) {
3875     I422ToRGB565Row = I422ToRGB565Row_Any_MSA;
3876     if (IS_ALIGNED(width, 8)) {
3877       I422ToRGB565Row = I422ToRGB565Row_MSA;
3878     }
3879   }
3880 #endif
3881 
3882   for (y = 0; y < height; ++y) {
3883     I422ToRGB565Row(src_y, src_u, src_v, dst_rgb565, &kYuvI601Constants, width);
3884     dst_rgb565 += dst_stride_rgb565;
3885     src_y += src_stride_y;
3886     src_u += src_stride_u;
3887     src_v += src_stride_v;
3888   }
3889   return 0;
3890 }
3891 
3892 // Ordered 8x8 dither for 888 to 565.  Values from 0 to 7.
3893 static const uint8_t kDither565_4x4[16] = {
3894     0, 4, 1, 5, 6, 2, 7, 3, 1, 5, 0, 4, 7, 3, 6, 2,
3895 };
3896 
3897 // Convert I420 to RGB565 with dithering.
3898 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)3899 int I420ToRGB565Dither(const uint8_t* src_y,
3900                        int src_stride_y,
3901                        const uint8_t* src_u,
3902                        int src_stride_u,
3903                        const uint8_t* src_v,
3904                        int src_stride_v,
3905                        uint8_t* dst_rgb565,
3906                        int dst_stride_rgb565,
3907                        const uint8_t* dither4x4,
3908                        int width,
3909                        int height) {
3910   int y;
3911   void (*I422ToARGBRow)(const uint8_t* y_buf, const uint8_t* u_buf,
3912                         const uint8_t* v_buf, uint8_t* rgb_buf,
3913                         const struct YuvConstants* yuvconstants, int width) =
3914       I422ToARGBRow_C;
3915   void (*ARGBToRGB565DitherRow)(const uint8_t* src_argb, uint8_t* dst_rgb,
3916                                 const uint32_t dither4, int width) =
3917       ARGBToRGB565DitherRow_C;
3918   if (!src_y || !src_u || !src_v || !dst_rgb565 || width <= 0 || height == 0) {
3919     return -1;
3920   }
3921   // Negative height means invert the image.
3922   if (height < 0) {
3923     height = -height;
3924     dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565;
3925     dst_stride_rgb565 = -dst_stride_rgb565;
3926   }
3927   if (!dither4x4) {
3928     dither4x4 = kDither565_4x4;
3929   }
3930 #if defined(HAS_I422TOARGBROW_SSSE3)
3931   if (TestCpuFlag(kCpuHasSSSE3)) {
3932     I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
3933     if (IS_ALIGNED(width, 8)) {
3934       I422ToARGBRow = I422ToARGBRow_SSSE3;
3935     }
3936   }
3937 #endif
3938 #if defined(HAS_I422TOARGBROW_AVX2)
3939   if (TestCpuFlag(kCpuHasAVX2)) {
3940     I422ToARGBRow = I422ToARGBRow_Any_AVX2;
3941     if (IS_ALIGNED(width, 16)) {
3942       I422ToARGBRow = I422ToARGBRow_AVX2;
3943     }
3944   }
3945 #endif
3946 #if defined(HAS_I422TOARGBROW_NEON)
3947   if (TestCpuFlag(kCpuHasNEON)) {
3948     I422ToARGBRow = I422ToARGBRow_Any_NEON;
3949     if (IS_ALIGNED(width, 8)) {
3950       I422ToARGBRow = I422ToARGBRow_NEON;
3951     }
3952   }
3953 #endif
3954 #if defined(HAS_I422TOARGBROW_MMI)
3955   if (TestCpuFlag(kCpuHasMMI)) {
3956     I422ToARGBRow = I422ToARGBRow_Any_MMI;
3957     if (IS_ALIGNED(width, 4)) {
3958       I422ToARGBRow = I422ToARGBRow_MMI;
3959     }
3960   }
3961 #endif
3962 #if defined(HAS_I422TOARGBROW_MSA)
3963   if (TestCpuFlag(kCpuHasMSA)) {
3964     I422ToARGBRow = I422ToARGBRow_Any_MSA;
3965     if (IS_ALIGNED(width, 8)) {
3966       I422ToARGBRow = I422ToARGBRow_MSA;
3967     }
3968   }
3969 #endif
3970 #if defined(HAS_ARGBTORGB565DITHERROW_SSE2)
3971   if (TestCpuFlag(kCpuHasSSE2)) {
3972     ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_SSE2;
3973     if (IS_ALIGNED(width, 4)) {
3974       ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_SSE2;
3975     }
3976   }
3977 #endif
3978 #if defined(HAS_ARGBTORGB565DITHERROW_AVX2)
3979   if (TestCpuFlag(kCpuHasAVX2)) {
3980     ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_AVX2;
3981     if (IS_ALIGNED(width, 8)) {
3982       ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_AVX2;
3983     }
3984   }
3985 #endif
3986 #if defined(HAS_ARGBTORGB565DITHERROW_NEON)
3987   if (TestCpuFlag(kCpuHasNEON)) {
3988     ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_NEON;
3989     if (IS_ALIGNED(width, 8)) {
3990       ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_NEON;
3991     }
3992   }
3993 #endif
3994 #if defined(HAS_ARGBTORGB565DITHERROW_MMI)
3995   if (TestCpuFlag(kCpuHasMMI)) {
3996     ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_MMI;
3997     if (IS_ALIGNED(width, 4)) {
3998       ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_MMI;
3999     }
4000   }
4001 #endif
4002 #if defined(HAS_ARGBTORGB565DITHERROW_MSA)
4003   if (TestCpuFlag(kCpuHasMSA)) {
4004     ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_MSA;
4005     if (IS_ALIGNED(width, 8)) {
4006       ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_MSA;
4007     }
4008   }
4009 #endif
4010   {
4011     // Allocate a row of argb.
4012     align_buffer_64(row_argb, width * 4);
4013     for (y = 0; y < height; ++y) {
4014       I422ToARGBRow(src_y, src_u, src_v, row_argb, &kYuvI601Constants, width);
4015       ARGBToRGB565DitherRow(row_argb, dst_rgb565,
4016                             *(const uint32_t*)(dither4x4 + ((y & 3) << 2)),
4017                             width);
4018       dst_rgb565 += dst_stride_rgb565;
4019       src_y += src_stride_y;
4020       if (y & 1) {
4021         src_u += src_stride_u;
4022         src_v += src_stride_v;
4023       }
4024     }
4025     free_aligned_buffer_64(row_argb);
4026   }
4027   return 0;
4028 }
4029 
4030 // Convert I420 to AR30 with matrix.
4031 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)4032 int I420ToAR30Matrix(const uint8_t* src_y,
4033                      int src_stride_y,
4034                      const uint8_t* src_u,
4035                      int src_stride_u,
4036                      const uint8_t* src_v,
4037                      int src_stride_v,
4038                      uint8_t* dst_ar30,
4039                      int dst_stride_ar30,
4040                      const struct YuvConstants* yuvconstants,
4041                      int width,
4042                      int height) {
4043   int y;
4044   void (*I422ToAR30Row)(const uint8_t* y_buf, const uint8_t* u_buf,
4045                         const uint8_t* v_buf, uint8_t* rgb_buf,
4046                         const struct YuvConstants* yuvconstants, int width) =
4047       I422ToAR30Row_C;
4048 
4049   if (!src_y || !src_u || !src_v || !dst_ar30 || width <= 0 || height == 0) {
4050     return -1;
4051   }
4052   // Negative height means invert the image.
4053   if (height < 0) {
4054     height = -height;
4055     dst_ar30 = dst_ar30 + (height - 1) * dst_stride_ar30;
4056     dst_stride_ar30 = -dst_stride_ar30;
4057   }
4058 
4059 #if defined(HAS_I422TOAR30ROW_SSSE3)
4060   if (TestCpuFlag(kCpuHasSSSE3)) {
4061     I422ToAR30Row = I422ToAR30Row_Any_SSSE3;
4062     if (IS_ALIGNED(width, 8)) {
4063       I422ToAR30Row = I422ToAR30Row_SSSE3;
4064     }
4065   }
4066 #endif
4067 #if defined(HAS_I422TOAR30ROW_AVX2)
4068   if (TestCpuFlag(kCpuHasAVX2)) {
4069     I422ToAR30Row = I422ToAR30Row_Any_AVX2;
4070     if (IS_ALIGNED(width, 16)) {
4071       I422ToAR30Row = I422ToAR30Row_AVX2;
4072     }
4073   }
4074 #endif
4075 
4076   for (y = 0; y < height; ++y) {
4077     I422ToAR30Row(src_y, src_u, src_v, dst_ar30, yuvconstants, width);
4078     dst_ar30 += dst_stride_ar30;
4079     src_y += src_stride_y;
4080     if (y & 1) {
4081       src_u += src_stride_u;
4082       src_v += src_stride_v;
4083     }
4084   }
4085   return 0;
4086 }
4087 
4088 // Convert I420 to AR30.
4089 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)4090 int I420ToAR30(const uint8_t* src_y,
4091                int src_stride_y,
4092                const uint8_t* src_u,
4093                int src_stride_u,
4094                const uint8_t* src_v,
4095                int src_stride_v,
4096                uint8_t* dst_ar30,
4097                int dst_stride_ar30,
4098                int width,
4099                int height) {
4100   return I420ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
4101                           src_stride_v, dst_ar30, dst_stride_ar30,
4102                           &kYuvI601Constants, width, height);
4103 }
4104 
4105 // Convert H420 to AR30.
4106 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)4107 int H420ToAR30(const uint8_t* src_y,
4108                int src_stride_y,
4109                const uint8_t* src_u,
4110                int src_stride_u,
4111                const uint8_t* src_v,
4112                int src_stride_v,
4113                uint8_t* dst_ar30,
4114                int dst_stride_ar30,
4115                int width,
4116                int height) {
4117   return I420ToAR30Matrix(src_y, src_stride_y, src_u, src_stride_u, src_v,
4118                           src_stride_v, dst_ar30, dst_stride_ar30,
4119                           &kYvuH709Constants, width, height);
4120 }
4121 
4122 #ifdef __cplusplus
4123 }  // extern "C"
4124 }  // namespace libyuv
4125 #endif
4126