• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 2012 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_from_argb.h"
12 
13 #include "libyuv/basic_types.h"
14 #include "libyuv/cpu_id.h"
15 #include "libyuv/planar_functions.h"
16 #include "libyuv/row.h"
17 
18 #ifdef __cplusplus
19 namespace libyuv {
20 extern "C" {
21 #endif
22 
23 // ARGB little endian (bgra in memory) to I444
24 LIBYUV_API
ARGBToI444(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_y,int dst_stride_y,uint8_t * dst_u,int dst_stride_u,uint8_t * dst_v,int dst_stride_v,int width,int height)25 int ARGBToI444(const uint8_t* src_argb,
26                int src_stride_argb,
27                uint8_t* dst_y,
28                int dst_stride_y,
29                uint8_t* dst_u,
30                int dst_stride_u,
31                uint8_t* dst_v,
32                int dst_stride_v,
33                int width,
34                int height) {
35   int y;
36   void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
37       ARGBToYRow_C;
38   void (*ARGBToUV444Row)(const uint8_t* src_argb, uint8_t* dst_u,
39                          uint8_t* dst_v, int width) = ARGBToUV444Row_C;
40   if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
41     return -1;
42   }
43   if (height < 0) {
44     height = -height;
45     src_argb = src_argb + (height - 1) * src_stride_argb;
46     src_stride_argb = -src_stride_argb;
47   }
48   // Coalesce rows.
49   if (src_stride_argb == width * 4 && dst_stride_y == width &&
50       dst_stride_u == width && dst_stride_v == width) {
51     width *= height;
52     height = 1;
53     src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0;
54   }
55 #if defined(HAS_ARGBTOUV444ROW_SSSE3)
56   if (TestCpuFlag(kCpuHasSSSE3)) {
57     ARGBToUV444Row = ARGBToUV444Row_Any_SSSE3;
58     if (IS_ALIGNED(width, 16)) {
59       ARGBToUV444Row = ARGBToUV444Row_SSSE3;
60     }
61   }
62 #endif
63 #if defined(HAS_ARGBTOUV444ROW_NEON)
64   if (TestCpuFlag(kCpuHasNEON)) {
65     ARGBToUV444Row = ARGBToUV444Row_Any_NEON;
66     if (IS_ALIGNED(width, 8)) {
67       ARGBToUV444Row = ARGBToUV444Row_NEON;
68     }
69   }
70 #endif
71 #if defined(HAS_ARGBTOUV444ROW_MSA)
72   if (TestCpuFlag(kCpuHasMSA)) {
73     ARGBToUV444Row = ARGBToUV444Row_Any_MSA;
74     if (IS_ALIGNED(width, 16)) {
75       ARGBToUV444Row = ARGBToUV444Row_MSA;
76     }
77   }
78 #endif
79 #if defined(HAS_ARGBTOUV444ROW_LSX)
80   if (TestCpuFlag(kCpuHasLSX)) {
81     ARGBToUV444Row = ARGBToUV444Row_Any_LSX;
82     if (IS_ALIGNED(width, 16)) {
83       ARGBToUV444Row = ARGBToUV444Row_LSX;
84     }
85   }
86 #endif
87 #if defined(HAS_ARGBTOUV444ROW_LASX)
88   if (TestCpuFlag(kCpuHasLASX)) {
89     ARGBToUV444Row = ARGBToUV444Row_Any_LASX;
90     if (IS_ALIGNED(width, 32)) {
91       ARGBToUV444Row = ARGBToUV444Row_LASX;
92     }
93   }
94 #endif
95 #if defined(HAS_ARGBTOYROW_SSSE3)
96   if (TestCpuFlag(kCpuHasSSSE3)) {
97     ARGBToYRow = ARGBToYRow_Any_SSSE3;
98     if (IS_ALIGNED(width, 16)) {
99       ARGBToYRow = ARGBToYRow_SSSE3;
100     }
101   }
102 #endif
103 #if defined(HAS_ARGBTOYROW_AVX2)
104   if (TestCpuFlag(kCpuHasAVX2)) {
105     ARGBToYRow = ARGBToYRow_Any_AVX2;
106     if (IS_ALIGNED(width, 32)) {
107       ARGBToYRow = ARGBToYRow_AVX2;
108     }
109   }
110 #endif
111 #if defined(HAS_ARGBTOYROW_NEON)
112   if (TestCpuFlag(kCpuHasNEON)) {
113     ARGBToYRow = ARGBToYRow_Any_NEON;
114     if (IS_ALIGNED(width, 16)) {
115       ARGBToYRow = ARGBToYRow_NEON;
116     }
117   }
118 #endif
119 #if defined(HAS_ARGBTOYROW_MSA)
120   if (TestCpuFlag(kCpuHasMSA)) {
121     ARGBToYRow = ARGBToYRow_Any_MSA;
122     if (IS_ALIGNED(width, 16)) {
123       ARGBToYRow = ARGBToYRow_MSA;
124     }
125   }
126 #endif
127 #if defined(HAS_ARGBTOYROW_LSX)
128   if (TestCpuFlag(kCpuHasLSX)) {
129     ARGBToYRow = ARGBToYRow_Any_LSX;
130     if (IS_ALIGNED(width, 16)) {
131       ARGBToYRow = ARGBToYRow_LSX;
132     }
133   }
134 #endif
135 #if defined(HAS_ARGBTOYROW_LASX)
136   if (TestCpuFlag(kCpuHasLASX)) {
137     ARGBToYRow = ARGBToYRow_Any_LASX;
138     if (IS_ALIGNED(width, 32)) {
139       ARGBToYRow = ARGBToYRow_LASX;
140     }
141   }
142 #endif
143 #if defined(HAS_ARGBTOYROW_RVV)
144   if (TestCpuFlag(kCpuHasRVV)) {
145     ARGBToYRow = ARGBToYRow_RVV;
146   }
147 #endif
148 
149   for (y = 0; y < height; ++y) {
150     ARGBToUV444Row(src_argb, dst_u, dst_v, width);
151     ARGBToYRow(src_argb, dst_y, width);
152     src_argb += src_stride_argb;
153     dst_y += dst_stride_y;
154     dst_u += dst_stride_u;
155     dst_v += dst_stride_v;
156   }
157   return 0;
158 }
159 
160 // ARGB little endian (bgra in memory) to I422
161 LIBYUV_API
ARGBToI422(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_y,int dst_stride_y,uint8_t * dst_u,int dst_stride_u,uint8_t * dst_v,int dst_stride_v,int width,int height)162 int ARGBToI422(const uint8_t* src_argb,
163                int src_stride_argb,
164                uint8_t* dst_y,
165                int dst_stride_y,
166                uint8_t* dst_u,
167                int dst_stride_u,
168                uint8_t* dst_v,
169                int dst_stride_v,
170                int width,
171                int height) {
172   int y;
173   void (*ARGBToUVRow)(const uint8_t* src_argb0, int src_stride_argb,
174                       uint8_t* dst_u, uint8_t* dst_v, int width) =
175       ARGBToUVRow_C;
176   void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
177       ARGBToYRow_C;
178   if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
179     return -1;
180   }
181   // Negative height means invert the image.
182   if (height < 0) {
183     height = -height;
184     src_argb = src_argb + (height - 1) * src_stride_argb;
185     src_stride_argb = -src_stride_argb;
186   }
187   // Coalesce rows.
188   if (src_stride_argb == width * 4 && dst_stride_y == width &&
189       dst_stride_u * 2 == width && dst_stride_v * 2 == width) {
190     width *= height;
191     height = 1;
192     src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0;
193   }
194 #if defined(HAS_ARGBTOYROW_SSSE3)
195   if (TestCpuFlag(kCpuHasSSSE3)) {
196     ARGBToYRow = ARGBToYRow_Any_SSSE3;
197     if (IS_ALIGNED(width, 16)) {
198       ARGBToYRow = ARGBToYRow_SSSE3;
199     }
200   }
201 #endif
202 #if defined(HAS_ARGBTOUVROW_SSSE3)
203   if (TestCpuFlag(kCpuHasSSSE3)) {
204     ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
205     if (IS_ALIGNED(width, 16)) {
206       ARGBToUVRow = ARGBToUVRow_SSSE3;
207     }
208   }
209 #endif
210 #if defined(HAS_ARGBTOYROW_AVX2)
211   if (TestCpuFlag(kCpuHasAVX2)) {
212     ARGBToYRow = ARGBToYRow_Any_AVX2;
213     if (IS_ALIGNED(width, 32)) {
214       ARGBToYRow = ARGBToYRow_AVX2;
215     }
216   }
217 #endif
218 #if defined(HAS_ARGBTOUVROW_AVX2)
219   if (TestCpuFlag(kCpuHasAVX2)) {
220     ARGBToUVRow = ARGBToUVRow_Any_AVX2;
221     if (IS_ALIGNED(width, 32)) {
222       ARGBToUVRow = ARGBToUVRow_AVX2;
223     }
224   }
225 #endif
226 #if defined(HAS_ARGBTOYROW_NEON)
227   if (TestCpuFlag(kCpuHasNEON)) {
228     ARGBToYRow = ARGBToYRow_Any_NEON;
229     if (IS_ALIGNED(width, 16)) {
230       ARGBToYRow = ARGBToYRow_NEON;
231     }
232   }
233 #endif
234 #if defined(HAS_ARGBTOUVROW_NEON)
235   if (TestCpuFlag(kCpuHasNEON)) {
236     ARGBToUVRow = ARGBToUVRow_Any_NEON;
237     if (IS_ALIGNED(width, 16)) {
238       ARGBToUVRow = ARGBToUVRow_NEON;
239     }
240   }
241 #endif
242 #if defined(HAS_ARGBTOYROW_MSA) && defined(HAS_ARGBTOUVROW_MSA)
243   if (TestCpuFlag(kCpuHasMSA)) {
244     ARGBToYRow = ARGBToYRow_Any_MSA;
245     ARGBToUVRow = ARGBToUVRow_Any_MSA;
246     if (IS_ALIGNED(width, 16)) {
247       ARGBToYRow = ARGBToYRow_MSA;
248     }
249     if (IS_ALIGNED(width, 32)) {
250       ARGBToUVRow = ARGBToUVRow_MSA;
251     }
252   }
253 #endif
254 #if defined(HAS_ARGBTOYROW_LSX)
255   if (TestCpuFlag(kCpuHasLSX)) {
256     ARGBToYRow = ARGBToYRow_Any_LSX;
257     if (IS_ALIGNED(width, 16)) {
258       ARGBToYRow = ARGBToYRow_LSX;
259     }
260   }
261 #endif
262 #if defined(HAS_ARGBTOYROW_LSX) && defined(HAS_ARGBTOUVROW_LSX)
263   if (TestCpuFlag(kCpuHasLSX)) {
264     ARGBToYRow = ARGBToYRow_Any_LSX;
265     ARGBToUVRow = ARGBToUVRow_Any_LSX;
266     if (IS_ALIGNED(width, 16)) {
267       ARGBToYRow = ARGBToYRow_LSX;
268       ARGBToUVRow = ARGBToUVRow_LSX;
269     }
270   }
271 #endif
272 #if defined(HAS_ARGBTOYROW_LASX) && defined(HAS_ARGBTOUVROW_LASX)
273   if (TestCpuFlag(kCpuHasLASX)) {
274     ARGBToYRow = ARGBToYRow_Any_LASX;
275     ARGBToUVRow = ARGBToUVRow_Any_LASX;
276     if (IS_ALIGNED(width, 32)) {
277       ARGBToYRow = ARGBToYRow_LASX;
278       ARGBToUVRow = ARGBToUVRow_LASX;
279     }
280   }
281 #endif
282 #if defined(HAS_ARGBTOYROW_RVV)
283   if (TestCpuFlag(kCpuHasRVV)) {
284     ARGBToYRow = ARGBToYRow_RVV;
285   }
286 #endif
287 
288   for (y = 0; y < height; ++y) {
289     ARGBToUVRow(src_argb, 0, dst_u, dst_v, width);
290     ARGBToYRow(src_argb, dst_y, width);
291     src_argb += src_stride_argb;
292     dst_y += dst_stride_y;
293     dst_u += dst_stride_u;
294     dst_v += dst_stride_v;
295   }
296   return 0;
297 }
298 
299 LIBYUV_API
ARGBToNV12(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_y,int dst_stride_y,uint8_t * dst_uv,int dst_stride_uv,int width,int height)300 int ARGBToNV12(const uint8_t* src_argb,
301                int src_stride_argb,
302                uint8_t* dst_y,
303                int dst_stride_y,
304                uint8_t* dst_uv,
305                int dst_stride_uv,
306                int width,
307                int height) {
308   int y;
309   int halfwidth = (width + 1) >> 1;
310   void (*ARGBToUVRow)(const uint8_t* src_argb0, int src_stride_argb,
311                       uint8_t* dst_u, uint8_t* dst_v, int width) =
312       ARGBToUVRow_C;
313   void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
314       ARGBToYRow_C;
315   void (*MergeUVRow_)(const uint8_t* src_u, const uint8_t* src_v,
316                       uint8_t* dst_uv, int width) = MergeUVRow_C;
317   if (!src_argb || !dst_y || !dst_uv || width <= 0 || height == 0) {
318     return -1;
319   }
320   // Negative height means invert the image.
321   if (height < 0) {
322     height = -height;
323     src_argb = src_argb + (height - 1) * src_stride_argb;
324     src_stride_argb = -src_stride_argb;
325   }
326 #if defined(HAS_ARGBTOYROW_NEON)
327   if (TestCpuFlag(kCpuHasNEON)) {
328     ARGBToYRow = ARGBToYRow_Any_NEON;
329     if (IS_ALIGNED(width, 16)) {
330       ARGBToYRow = ARGBToYRow_NEON;
331     }
332   }
333 #endif
334 #if defined(HAS_ARGBTOUVROW_NEON)
335   if (TestCpuFlag(kCpuHasNEON)) {
336     ARGBToUVRow = ARGBToUVRow_Any_NEON;
337     if (IS_ALIGNED(width, 16)) {
338       ARGBToUVRow = ARGBToUVRow_NEON;
339     }
340   }
341 #endif
342 #if defined(HAS_ARGBTOYROW_SSSE3)
343   if (TestCpuFlag(kCpuHasSSSE3)) {
344     ARGBToYRow = ARGBToYRow_Any_SSSE3;
345     if (IS_ALIGNED(width, 16)) {
346       ARGBToYRow = ARGBToYRow_SSSE3;
347     }
348   }
349 #endif
350 #if defined(HAS_ARGBTOUVROW_SSSE3)
351   if (TestCpuFlag(kCpuHasSSSE3)) {
352     ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
353     if (IS_ALIGNED(width, 16)) {
354       ARGBToUVRow = ARGBToUVRow_SSSE3;
355     }
356   }
357 #endif
358 #if defined(HAS_ARGBTOYROW_AVX2)
359   if (TestCpuFlag(kCpuHasAVX2)) {
360     ARGBToYRow = ARGBToYRow_Any_AVX2;
361     if (IS_ALIGNED(width, 32)) {
362       ARGBToYRow = ARGBToYRow_AVX2;
363     }
364   }
365 #endif
366 #if defined(HAS_ARGBTOUVROW_AVX2)
367   if (TestCpuFlag(kCpuHasAVX2)) {
368     ARGBToUVRow = ARGBToUVRow_Any_AVX2;
369     if (IS_ALIGNED(width, 32)) {
370       ARGBToUVRow = ARGBToUVRow_AVX2;
371     }
372   }
373 #endif
374 #if defined(HAS_ARGBTOYROW_MSA) && defined(HAS_ARGBTOUVROW_MSA)
375   if (TestCpuFlag(kCpuHasMSA)) {
376     ARGBToYRow = ARGBToYRow_Any_MSA;
377     ARGBToUVRow = ARGBToUVRow_Any_MSA;
378     if (IS_ALIGNED(width, 16)) {
379       ARGBToYRow = ARGBToYRow_MSA;
380     }
381     if (IS_ALIGNED(width, 32)) {
382       ARGBToUVRow = ARGBToUVRow_MSA;
383     }
384   }
385 #endif
386 #if defined(HAS_ARGBTOYROW_LSX)
387   if (TestCpuFlag(kCpuHasLSX)) {
388     ARGBToYRow = ARGBToYRow_Any_LSX;
389     if (IS_ALIGNED(width, 16)) {
390       ARGBToYRow = ARGBToYRow_LSX;
391     }
392   }
393 #endif
394 #if defined(HAS_ARGBTOYROW_LASX) && defined(HAS_ARGBTOUVROW_LASX)
395   if (TestCpuFlag(kCpuHasLASX)) {
396     ARGBToYRow = ARGBToYRow_Any_LASX;
397     ARGBToUVRow = ARGBToUVRow_Any_LASX;
398     if (IS_ALIGNED(width, 32)) {
399       ARGBToYRow = ARGBToYRow_LASX;
400       ARGBToUVRow = ARGBToUVRow_LASX;
401     }
402   }
403 #endif
404 #if defined(HAS_ARGBTOYROW_RVV)
405   if (TestCpuFlag(kCpuHasRVV)) {
406     ARGBToYRow = ARGBToYRow_RVV;
407   }
408 #endif
409 #if defined(HAS_MERGEUVROW_SSE2)
410   if (TestCpuFlag(kCpuHasSSE2)) {
411     MergeUVRow_ = MergeUVRow_Any_SSE2;
412     if (IS_ALIGNED(halfwidth, 16)) {
413       MergeUVRow_ = MergeUVRow_SSE2;
414     }
415   }
416 #endif
417 #if defined(HAS_MERGEUVROW_AVX2)
418   if (TestCpuFlag(kCpuHasAVX2)) {
419     MergeUVRow_ = MergeUVRow_Any_AVX2;
420     if (IS_ALIGNED(halfwidth, 16)) {
421       MergeUVRow_ = MergeUVRow_AVX2;
422     }
423   }
424 #endif
425 #if defined(HAS_MERGEUVROW_AVX512BW)
426   if (TestCpuFlag(kCpuHasAVX512BW)) {
427     MergeUVRow_ = MergeUVRow_Any_AVX512BW;
428     if (IS_ALIGNED(halfwidth, 32)) {
429       MergeUVRow_ = MergeUVRow_AVX512BW;
430     }
431   }
432 #endif
433 #if defined(HAS_MERGEUVROW_NEON)
434   if (TestCpuFlag(kCpuHasNEON)) {
435     MergeUVRow_ = MergeUVRow_Any_NEON;
436     if (IS_ALIGNED(halfwidth, 16)) {
437       MergeUVRow_ = MergeUVRow_NEON;
438     }
439   }
440 #endif
441 #if defined(HAS_MERGEUVROW_MSA)
442   if (TestCpuFlag(kCpuHasMSA)) {
443     MergeUVRow_ = MergeUVRow_Any_MSA;
444     if (IS_ALIGNED(halfwidth, 16)) {
445       MergeUVRow_ = MergeUVRow_MSA;
446     }
447   }
448 #endif
449 #if defined(HAS_MERGEUVROW_LSX)
450   if (TestCpuFlag(kCpuHasLSX)) {
451     MergeUVRow_ = MergeUVRow_Any_LSX;
452     if (IS_ALIGNED(halfwidth, 16)) {
453       MergeUVRow_ = MergeUVRow_LSX;
454     }
455   }
456 #endif
457 #if defined(HAS_MERGEUVROW_RVV)
458   if (TestCpuFlag(kCpuHasRVV)) {
459     MergeUVRow_ = MergeUVRow_RVV;
460   }
461 #endif
462   {
463     // Allocate a rows of uv.
464     align_buffer_64(row_u, ((halfwidth + 31) & ~31) * 2);
465     uint8_t* row_v = row_u + ((halfwidth + 31) & ~31);
466     if (!row_u)
467       return 1;
468 
469     for (y = 0; y < height - 1; y += 2) {
470       ARGBToUVRow(src_argb, src_stride_argb, row_u, row_v, width);
471       MergeUVRow_(row_u, row_v, dst_uv, halfwidth);
472       ARGBToYRow(src_argb, dst_y, width);
473       ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width);
474       src_argb += src_stride_argb * 2;
475       dst_y += dst_stride_y * 2;
476       dst_uv += dst_stride_uv;
477     }
478     if (height & 1) {
479       ARGBToUVRow(src_argb, 0, row_u, row_v, width);
480       MergeUVRow_(row_u, row_v, dst_uv, halfwidth);
481       ARGBToYRow(src_argb, dst_y, width);
482     }
483     free_aligned_buffer_64(row_u);
484   }
485   return 0;
486 }
487 
488 // Same as NV12 but U and V swapped.
489 LIBYUV_API
ARGBToNV21(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_y,int dst_stride_y,uint8_t * dst_vu,int dst_stride_vu,int width,int height)490 int ARGBToNV21(const uint8_t* src_argb,
491                int src_stride_argb,
492                uint8_t* dst_y,
493                int dst_stride_y,
494                uint8_t* dst_vu,
495                int dst_stride_vu,
496                int width,
497                int height) {
498   int y;
499   int halfwidth = (width + 1) >> 1;
500   void (*ARGBToUVRow)(const uint8_t* src_argb0, int src_stride_argb,
501                       uint8_t* dst_u, uint8_t* dst_v, int width) =
502       ARGBToUVRow_C;
503   void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
504       ARGBToYRow_C;
505   void (*MergeUVRow_)(const uint8_t* src_u, const uint8_t* src_v,
506                       uint8_t* dst_vu, int width) = MergeUVRow_C;
507   if (!src_argb || !dst_y || !dst_vu || width <= 0 || height == 0) {
508     return -1;
509   }
510   // Negative height means invert the image.
511   if (height < 0) {
512     height = -height;
513     src_argb = src_argb + (height - 1) * src_stride_argb;
514     src_stride_argb = -src_stride_argb;
515   }
516 #if defined(HAS_ARGBTOYROW_SSSE3)
517   if (TestCpuFlag(kCpuHasSSSE3)) {
518     ARGBToYRow = ARGBToYRow_Any_SSSE3;
519     if (IS_ALIGNED(width, 16)) {
520       ARGBToYRow = ARGBToYRow_SSSE3;
521     }
522   }
523 #endif
524 #if defined(HAS_ARGBTOUVROW_SSSE3)
525   if (TestCpuFlag(kCpuHasSSSE3)) {
526     ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
527     if (IS_ALIGNED(width, 16)) {
528       ARGBToUVRow = ARGBToUVRow_SSSE3;
529     }
530   }
531 #endif
532 #if defined(HAS_ARGBTOYROW_AVX2)
533   if (TestCpuFlag(kCpuHasAVX2)) {
534     ARGBToYRow = ARGBToYRow_Any_AVX2;
535     if (IS_ALIGNED(width, 32)) {
536       ARGBToYRow = ARGBToYRow_AVX2;
537     }
538   }
539 #endif
540 #if defined(HAS_ARGBTOUVROW_AVX2)
541   if (TestCpuFlag(kCpuHasAVX2)) {
542     ARGBToUVRow = ARGBToUVRow_Any_AVX2;
543     if (IS_ALIGNED(width, 32)) {
544       ARGBToUVRow = ARGBToUVRow_AVX2;
545     }
546   }
547 #endif
548 #if defined(HAS_ARGBTOYROW_NEON)
549   if (TestCpuFlag(kCpuHasNEON)) {
550     ARGBToYRow = ARGBToYRow_Any_NEON;
551     if (IS_ALIGNED(width, 16)) {
552       ARGBToYRow = ARGBToYRow_NEON;
553     }
554   }
555 #endif
556 #if defined(HAS_ARGBTOUVROW_NEON)
557   if (TestCpuFlag(kCpuHasNEON)) {
558     ARGBToUVRow = ARGBToUVRow_Any_NEON;
559     if (IS_ALIGNED(width, 16)) {
560       ARGBToUVRow = ARGBToUVRow_NEON;
561     }
562   }
563 #endif
564 #if defined(HAS_ARGBTOYROW_MSA) && defined(HAS_ARGBTOUVROW_MSA)
565   if (TestCpuFlag(kCpuHasMSA)) {
566     ARGBToYRow = ARGBToYRow_Any_MSA;
567     ARGBToUVRow = ARGBToUVRow_Any_MSA;
568     if (IS_ALIGNED(width, 16)) {
569       ARGBToYRow = ARGBToYRow_MSA;
570     }
571     if (IS_ALIGNED(width, 32)) {
572       ARGBToUVRow = ARGBToUVRow_MSA;
573     }
574   }
575 #endif
576 #if defined(HAS_ARGBTOYROW_LSX)
577   if (TestCpuFlag(kCpuHasLSX)) {
578     ARGBToYRow = ARGBToYRow_Any_LSX;
579     if (IS_ALIGNED(width, 16)) {
580       ARGBToYRow = ARGBToYRow_LSX;
581     }
582   }
583 #endif
584 #if defined(HAS_ARGBTOYROW_LSX) && defined(HAS_ARGBTOUVROW_LSX)
585   if (TestCpuFlag(kCpuHasLSX)) {
586     ARGBToYRow = ARGBToYRow_Any_LSX;
587     ARGBToUVRow = ARGBToUVRow_Any_LSX;
588     if (IS_ALIGNED(width, 16)) {
589       ARGBToYRow = ARGBToYRow_LSX;
590       ARGBToUVRow = ARGBToUVRow_LSX;
591     }
592   }
593 #endif
594 #if defined(HAS_ARGBTOYROW_LASX) && defined(HAS_ARGBTOUVROW_LASX)
595   if (TestCpuFlag(kCpuHasLASX)) {
596     ARGBToYRow = ARGBToYRow_Any_LASX;
597     ARGBToUVRow = ARGBToUVRow_Any_LASX;
598     if (IS_ALIGNED(width, 32)) {
599       ARGBToYRow = ARGBToYRow_LASX;
600       ARGBToUVRow = ARGBToUVRow_LASX;
601     }
602   }
603 #endif
604 #if defined(HAS_ARGBTOYROW_RVV)
605   if (TestCpuFlag(kCpuHasRVV)) {
606     ARGBToYRow = ARGBToYRow_RVV;
607   }
608 #endif
609 #if defined(HAS_MERGEUVROW_SSE2)
610   if (TestCpuFlag(kCpuHasSSE2)) {
611     MergeUVRow_ = MergeUVRow_Any_SSE2;
612     if (IS_ALIGNED(halfwidth, 16)) {
613       MergeUVRow_ = MergeUVRow_SSE2;
614     }
615   }
616 #endif
617 #if defined(HAS_MERGEUVROW_AVX2)
618   if (TestCpuFlag(kCpuHasAVX2)) {
619     MergeUVRow_ = MergeUVRow_Any_AVX2;
620     if (IS_ALIGNED(halfwidth, 16)) {
621       MergeUVRow_ = MergeUVRow_AVX2;
622     }
623   }
624 #endif
625 #if defined(HAS_MERGEUVROW_AVX512BW)
626   if (TestCpuFlag(kCpuHasAVX512BW)) {
627     MergeUVRow_ = MergeUVRow_Any_AVX512BW;
628     if (IS_ALIGNED(halfwidth, 64)) {
629       MergeUVRow_ = MergeUVRow_AVX512BW;
630     }
631   }
632 #endif
633 #if defined(HAS_MERGEUVROW_NEON)
634   if (TestCpuFlag(kCpuHasNEON)) {
635     MergeUVRow_ = MergeUVRow_Any_NEON;
636     if (IS_ALIGNED(halfwidth, 16)) {
637       MergeUVRow_ = MergeUVRow_NEON;
638     }
639   }
640 #endif
641 #if defined(HAS_MERGEUVROW_MSA)
642   if (TestCpuFlag(kCpuHasMSA)) {
643     MergeUVRow_ = MergeUVRow_Any_MSA;
644     if (IS_ALIGNED(halfwidth, 16)) {
645       MergeUVRow_ = MergeUVRow_MSA;
646     }
647   }
648 #endif
649 #if defined(HAS_MERGEUVROW_LSX)
650   if (TestCpuFlag(kCpuHasLSX)) {
651     MergeUVRow_ = MergeUVRow_Any_LSX;
652     if (IS_ALIGNED(halfwidth, 16)) {
653       MergeUVRow_ = MergeUVRow_LSX;
654     }
655   }
656 #endif
657 #if defined(HAS_MERGEUVROW_RVV)
658   if (TestCpuFlag(kCpuHasRVV)) {
659     MergeUVRow_ = MergeUVRow_RVV;
660   }
661 #endif
662   {
663     // Allocate a rows of uv.
664     align_buffer_64(row_u, ((halfwidth + 31) & ~31) * 2);
665     uint8_t* row_v = row_u + ((halfwidth + 31) & ~31);
666     if (!row_u)
667       return 1;
668 
669     for (y = 0; y < height - 1; y += 2) {
670       ARGBToUVRow(src_argb, src_stride_argb, row_u, row_v, width);
671       MergeUVRow_(row_v, row_u, dst_vu, halfwidth);
672       ARGBToYRow(src_argb, dst_y, width);
673       ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width);
674       src_argb += src_stride_argb * 2;
675       dst_y += dst_stride_y * 2;
676       dst_vu += dst_stride_vu;
677     }
678     if (height & 1) {
679       ARGBToUVRow(src_argb, 0, row_u, row_v, width);
680       MergeUVRow_(row_v, row_u, dst_vu, halfwidth);
681       ARGBToYRow(src_argb, dst_y, width);
682     }
683     free_aligned_buffer_64(row_u);
684   }
685   return 0;
686 }
687 
688 LIBYUV_API
ABGRToNV12(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_y,int dst_stride_y,uint8_t * dst_uv,int dst_stride_uv,int width,int height)689 int ABGRToNV12(const uint8_t* src_abgr,
690                int src_stride_abgr,
691                uint8_t* dst_y,
692                int dst_stride_y,
693                uint8_t* dst_uv,
694                int dst_stride_uv,
695                int width,
696                int height) {
697   int y;
698   int halfwidth = (width + 1) >> 1;
699   void (*ABGRToUVRow)(const uint8_t* src_abgr0, int src_stride_abgr,
700                       uint8_t* dst_u, uint8_t* dst_v, int width) =
701       ABGRToUVRow_C;
702   void (*ABGRToYRow)(const uint8_t* src_abgr, uint8_t* dst_y, int width) =
703       ABGRToYRow_C;
704   void (*MergeUVRow_)(const uint8_t* src_u, const uint8_t* src_v,
705                       uint8_t* dst_uv, int width) = MergeUVRow_C;
706   if (!src_abgr || !dst_y || !dst_uv || width <= 0 || height == 0) {
707     return -1;
708   }
709   // Negative height means invert the image.
710   if (height < 0) {
711     height = -height;
712     src_abgr = src_abgr + (height - 1) * src_stride_abgr;
713     src_stride_abgr = -src_stride_abgr;
714   }
715 #if defined(HAS_ABGRTOYROW_SSSE3)
716   if (TestCpuFlag(kCpuHasSSSE3)) {
717     ABGRToYRow = ABGRToYRow_Any_SSSE3;
718     if (IS_ALIGNED(width, 16)) {
719       ABGRToYRow = ABGRToYRow_SSSE3;
720     }
721   }
722 #endif
723 #if defined(HAS_ABGRTOUVROW_SSSE3)
724   if (TestCpuFlag(kCpuHasSSSE3)) {
725     ABGRToUVRow = ABGRToUVRow_Any_SSSE3;
726     if (IS_ALIGNED(width, 16)) {
727       ABGRToUVRow = ABGRToUVRow_SSSE3;
728     }
729   }
730 #endif
731 #if defined(HAS_ABGRTOYROW_AVX2)
732   if (TestCpuFlag(kCpuHasAVX2)) {
733     ABGRToYRow = ABGRToYRow_Any_AVX2;
734     if (IS_ALIGNED(width, 32)) {
735       ABGRToYRow = ABGRToYRow_AVX2;
736     }
737   }
738 #endif
739 #if defined(HAS_ABGRTOUVROW_AVX2)
740   if (TestCpuFlag(kCpuHasAVX2)) {
741     ABGRToUVRow = ABGRToUVRow_Any_AVX2;
742     if (IS_ALIGNED(width, 32)) {
743       ABGRToUVRow = ABGRToUVRow_AVX2;
744     }
745   }
746 #endif
747 #if defined(HAS_ABGRTOYROW_NEON)
748   if (TestCpuFlag(kCpuHasNEON)) {
749     ABGRToYRow = ABGRToYRow_Any_NEON;
750     if (IS_ALIGNED(width, 16)) {
751       ABGRToYRow = ABGRToYRow_NEON;
752     }
753   }
754 #endif
755 #if defined(HAS_ABGRTOUVROW_NEON)
756   if (TestCpuFlag(kCpuHasNEON)) {
757     ABGRToUVRow = ABGRToUVRow_Any_NEON;
758     if (IS_ALIGNED(width, 16)) {
759       ABGRToUVRow = ABGRToUVRow_NEON;
760     }
761   }
762 #endif
763 #if defined(HAS_ABGRTOYROW_MSA) && defined(HAS_ABGRTOUVROW_MSA)
764   if (TestCpuFlag(kCpuHasMSA)) {
765     ABGRToYRow = ABGRToYRow_Any_MSA;
766     ABGRToUVRow = ABGRToUVRow_Any_MSA;
767     if (IS_ALIGNED(width, 16)) {
768       ABGRToYRow = ABGRToYRow_MSA;
769     }
770     if (IS_ALIGNED(width, 32)) {
771       ABGRToUVRow = ABGRToUVRow_MSA;
772     }
773   }
774 #endif
775 #if defined(HAS_ABGRTOYROW_LSX)
776   if (TestCpuFlag(kCpuHasLSX)) {
777     ABGRToYRow = ABGRToYRow_Any_LSX;
778     if (IS_ALIGNED(width, 16)) {
779       ABGRToYRow = ABGRToYRow_LSX;
780     }
781   }
782 #endif
783 #if defined(HAS_ABGRTOYROW_LASX)
784   if (TestCpuFlag(kCpuHasLASX)) {
785     ABGRToYRow = ABGRToYRow_Any_LASX;
786     if (IS_ALIGNED(width, 32)) {
787       ABGRToYRow = ABGRToYRow_LASX;
788     }
789   }
790 #endif
791 #if defined(HAS_ABGRTOYROW_RVV)
792   if (TestCpuFlag(kCpuHasRVV)) {
793     ABGRToYRow = ABGRToYRow_RVV;
794   }
795 #endif
796 #if defined(HAS_MERGEUVROW_SSE2)
797   if (TestCpuFlag(kCpuHasSSE2)) {
798     MergeUVRow_ = MergeUVRow_Any_SSE2;
799     if (IS_ALIGNED(halfwidth, 16)) {
800       MergeUVRow_ = MergeUVRow_SSE2;
801     }
802   }
803 #endif
804 #if defined(HAS_MERGEUVROW_AVX2)
805   if (TestCpuFlag(kCpuHasAVX2)) {
806     MergeUVRow_ = MergeUVRow_Any_AVX2;
807     if (IS_ALIGNED(halfwidth, 16)) {
808       MergeUVRow_ = MergeUVRow_AVX2;
809     }
810   }
811 #endif
812 #if defined(HAS_MERGEUVROW_AVX512BW)
813   if (TestCpuFlag(kCpuHasAVX512BW)) {
814     MergeUVRow_ = MergeUVRow_Any_AVX512BW;
815     if (IS_ALIGNED(halfwidth, 64)) {
816       MergeUVRow_ = MergeUVRow_AVX512BW;
817     }
818   }
819 #endif
820 #if defined(HAS_MERGEUVROW_NEON)
821   if (TestCpuFlag(kCpuHasNEON)) {
822     MergeUVRow_ = MergeUVRow_Any_NEON;
823     if (IS_ALIGNED(halfwidth, 16)) {
824       MergeUVRow_ = MergeUVRow_NEON;
825     }
826   }
827 #endif
828 #if defined(HAS_MERGEUVROW_MSA)
829   if (TestCpuFlag(kCpuHasMSA)) {
830     MergeUVRow_ = MergeUVRow_Any_MSA;
831     if (IS_ALIGNED(halfwidth, 16)) {
832       MergeUVRow_ = MergeUVRow_MSA;
833     }
834   }
835 #endif
836 #if defined(HAS_MERGEUVROW_LSX)
837   if (TestCpuFlag(kCpuHasLSX)) {
838     MergeUVRow_ = MergeUVRow_Any_LSX;
839     if (IS_ALIGNED(halfwidth, 16)) {
840       MergeUVRow_ = MergeUVRow_LSX;
841     }
842   }
843 #endif
844 #if defined(HAS_MERGEUVROW_RVV)
845   if (TestCpuFlag(kCpuHasRVV)) {
846     MergeUVRow_ = MergeUVRow_RVV;
847   }
848 #endif
849   {
850     // Allocate a rows of uv.
851     align_buffer_64(row_u, ((halfwidth + 31) & ~31) * 2);
852     uint8_t* row_v = row_u + ((halfwidth + 31) & ~31);
853     if (!row_u)
854       return 1;
855 
856     for (y = 0; y < height - 1; y += 2) {
857       ABGRToUVRow(src_abgr, src_stride_abgr, row_u, row_v, width);
858       MergeUVRow_(row_u, row_v, dst_uv, halfwidth);
859       ABGRToYRow(src_abgr, dst_y, width);
860       ABGRToYRow(src_abgr + src_stride_abgr, dst_y + dst_stride_y, width);
861       src_abgr += src_stride_abgr * 2;
862       dst_y += dst_stride_y * 2;
863       dst_uv += dst_stride_uv;
864     }
865     if (height & 1) {
866       ABGRToUVRow(src_abgr, 0, row_u, row_v, width);
867       MergeUVRow_(row_u, row_v, dst_uv, halfwidth);
868       ABGRToYRow(src_abgr, dst_y, width);
869     }
870     free_aligned_buffer_64(row_u);
871   }
872   return 0;
873 }
874 
875 // Same as NV12 but U and V swapped.
876 LIBYUV_API
ABGRToNV21(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_y,int dst_stride_y,uint8_t * dst_vu,int dst_stride_vu,int width,int height)877 int ABGRToNV21(const uint8_t* src_abgr,
878                int src_stride_abgr,
879                uint8_t* dst_y,
880                int dst_stride_y,
881                uint8_t* dst_vu,
882                int dst_stride_vu,
883                int width,
884                int height) {
885   int y;
886   int halfwidth = (width + 1) >> 1;
887   void (*ABGRToUVRow)(const uint8_t* src_abgr0, int src_stride_abgr,
888                       uint8_t* dst_u, uint8_t* dst_v, int width) =
889       ABGRToUVRow_C;
890   void (*ABGRToYRow)(const uint8_t* src_abgr, uint8_t* dst_y, int width) =
891       ABGRToYRow_C;
892   void (*MergeUVRow_)(const uint8_t* src_u, const uint8_t* src_v,
893                       uint8_t* dst_vu, int width) = MergeUVRow_C;
894   if (!src_abgr || !dst_y || !dst_vu || width <= 0 || height == 0) {
895     return -1;
896   }
897   // Negative height means invert the image.
898   if (height < 0) {
899     height = -height;
900     src_abgr = src_abgr + (height - 1) * src_stride_abgr;
901     src_stride_abgr = -src_stride_abgr;
902   }
903 #if defined(HAS_ABGRTOYROW_SSSE3)
904   if (TestCpuFlag(kCpuHasSSSE3)) {
905     ABGRToYRow = ABGRToYRow_Any_SSSE3;
906     if (IS_ALIGNED(width, 16)) {
907       ABGRToYRow = ABGRToYRow_SSSE3;
908     }
909   }
910 #endif
911 #if defined(HAS_ABGRTOUVROW_SSSE3)
912   if (TestCpuFlag(kCpuHasSSSE3)) {
913     ABGRToUVRow = ABGRToUVRow_Any_SSSE3;
914     if (IS_ALIGNED(width, 16)) {
915       ABGRToUVRow = ABGRToUVRow_SSSE3;
916     }
917   }
918 #endif
919 #if defined(HAS_ABGRTOYROW_AVX2)
920   if (TestCpuFlag(kCpuHasAVX2)) {
921     ABGRToYRow = ABGRToYRow_Any_AVX2;
922     if (IS_ALIGNED(width, 32)) {
923       ABGRToYRow = ABGRToYRow_AVX2;
924     }
925   }
926 #endif
927 #if defined(HAS_ABGRTOUVROW_AVX2)
928   if (TestCpuFlag(kCpuHasAVX2)) {
929     ABGRToUVRow = ABGRToUVRow_Any_AVX2;
930     if (IS_ALIGNED(width, 32)) {
931       ABGRToUVRow = ABGRToUVRow_AVX2;
932     }
933   }
934 #endif
935 #if defined(HAS_ABGRTOYROW_NEON)
936   if (TestCpuFlag(kCpuHasNEON)) {
937     ABGRToYRow = ABGRToYRow_Any_NEON;
938     if (IS_ALIGNED(width, 16)) {
939       ABGRToYRow = ABGRToYRow_NEON;
940     }
941   }
942 #endif
943 #if defined(HAS_ABGRTOUVROW_NEON)
944   if (TestCpuFlag(kCpuHasNEON)) {
945     ABGRToUVRow = ABGRToUVRow_Any_NEON;
946     if (IS_ALIGNED(width, 16)) {
947       ABGRToUVRow = ABGRToUVRow_NEON;
948     }
949   }
950 #endif
951 #if defined(HAS_ABGRTOYROW_MSA) && defined(HAS_ABGRTOUVROW_MSA)
952   if (TestCpuFlag(kCpuHasMSA)) {
953     ABGRToYRow = ABGRToYRow_Any_MSA;
954     ABGRToUVRow = ABGRToUVRow_Any_MSA;
955     if (IS_ALIGNED(width, 16)) {
956       ABGRToYRow = ABGRToYRow_MSA;
957     }
958     if (IS_ALIGNED(width, 32)) {
959       ABGRToUVRow = ABGRToUVRow_MSA;
960     }
961   }
962 #endif
963 #if defined(HAS_ABGRTOYROW_LSX)
964   if (TestCpuFlag(kCpuHasLSX)) {
965     ABGRToYRow = ABGRToYRow_Any_LSX;
966     if (IS_ALIGNED(width, 16)) {
967       ABGRToYRow = ABGRToYRow_LSX;
968     }
969   }
970 #endif
971 #if defined(HAS_ABGRTOYROW_LASX)
972   if (TestCpuFlag(kCpuHasLASX)) {
973     ABGRToYRow = ABGRToYRow_Any_LASX;
974     if (IS_ALIGNED(width, 32)) {
975       ABGRToYRow = ABGRToYRow_LASX;
976     }
977   }
978 #endif
979 #if defined(HAS_ABGRTOYROW_RVV)
980   if (TestCpuFlag(kCpuHasRVV)) {
981     ABGRToYRow = ABGRToYRow_RVV;
982   }
983 #endif
984 #if defined(HAS_MERGEUVROW_SSE2)
985   if (TestCpuFlag(kCpuHasSSE2)) {
986     MergeUVRow_ = MergeUVRow_Any_SSE2;
987     if (IS_ALIGNED(halfwidth, 16)) {
988       MergeUVRow_ = MergeUVRow_SSE2;
989     }
990   }
991 #endif
992 #if defined(HAS_MERGEUVROW_AVX2)
993   if (TestCpuFlag(kCpuHasAVX2)) {
994     MergeUVRow_ = MergeUVRow_Any_AVX2;
995     if (IS_ALIGNED(halfwidth, 16)) {
996       MergeUVRow_ = MergeUVRow_AVX2;
997     }
998   }
999 #endif
1000 #if defined(HAS_MERGEUVROW_AVX512BW)
1001   if (TestCpuFlag(kCpuHasAVX512BW)) {
1002     MergeUVRow_ = MergeUVRow_Any_AVX512BW;
1003     if (IS_ALIGNED(halfwidth, 64)) {
1004       MergeUVRow_ = MergeUVRow_AVX512BW;
1005     }
1006   }
1007 #endif
1008 #if defined(HAS_MERGEUVROW_NEON)
1009   if (TestCpuFlag(kCpuHasNEON)) {
1010     MergeUVRow_ = MergeUVRow_Any_NEON;
1011     if (IS_ALIGNED(halfwidth, 16)) {
1012       MergeUVRow_ = MergeUVRow_NEON;
1013     }
1014   }
1015 #endif
1016 #if defined(HAS_MERGEUVROW_MSA)
1017   if (TestCpuFlag(kCpuHasMSA)) {
1018     MergeUVRow_ = MergeUVRow_Any_MSA;
1019     if (IS_ALIGNED(halfwidth, 16)) {
1020       MergeUVRow_ = MergeUVRow_MSA;
1021     }
1022   }
1023 #endif
1024 #if defined(HAS_MERGEUVROW_LSX)
1025   if (TestCpuFlag(kCpuHasLSX)) {
1026     MergeUVRow_ = MergeUVRow_Any_LSX;
1027     if (IS_ALIGNED(halfwidth, 16)) {
1028       MergeUVRow_ = MergeUVRow_LSX;
1029     }
1030   }
1031 #endif
1032 #if defined(HAS_MERGEUVROW_RVV)
1033   if (TestCpuFlag(kCpuHasRVV)) {
1034     MergeUVRow_ = MergeUVRow_RVV;
1035   }
1036 #endif
1037   {
1038     // Allocate a rows of uv.
1039     align_buffer_64(row_u, ((halfwidth + 31) & ~31) * 2);
1040     uint8_t* row_v = row_u + ((halfwidth + 31) & ~31);
1041     if (!row_u)
1042       return 1;
1043 
1044     for (y = 0; y < height - 1; y += 2) {
1045       ABGRToUVRow(src_abgr, src_stride_abgr, row_u, row_v, width);
1046       MergeUVRow_(row_v, row_u, dst_vu, halfwidth);
1047       ABGRToYRow(src_abgr, dst_y, width);
1048       ABGRToYRow(src_abgr + src_stride_abgr, dst_y + dst_stride_y, width);
1049       src_abgr += src_stride_abgr * 2;
1050       dst_y += dst_stride_y * 2;
1051       dst_vu += dst_stride_vu;
1052     }
1053     if (height & 1) {
1054       ABGRToUVRow(src_abgr, 0, row_u, row_v, width);
1055       MergeUVRow_(row_v, row_u, dst_vu, halfwidth);
1056       ABGRToYRow(src_abgr, dst_y, width);
1057     }
1058     free_aligned_buffer_64(row_u);
1059   }
1060   return 0;
1061 }
1062 
1063 // Convert ARGB to YUY2.
1064 LIBYUV_API
ARGBToYUY2(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_yuy2,int dst_stride_yuy2,int width,int height)1065 int ARGBToYUY2(const uint8_t* src_argb,
1066                int src_stride_argb,
1067                uint8_t* dst_yuy2,
1068                int dst_stride_yuy2,
1069                int width,
1070                int height) {
1071   int y;
1072   void (*ARGBToUVRow)(const uint8_t* src_argb, int src_stride_argb,
1073                       uint8_t* dst_u, uint8_t* dst_v, int width) =
1074       ARGBToUVRow_C;
1075   void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
1076       ARGBToYRow_C;
1077   void (*I422ToYUY2Row)(const uint8_t* src_y, const uint8_t* src_u,
1078                         const uint8_t* src_v, uint8_t* dst_yuy2, int width) =
1079       I422ToYUY2Row_C;
1080 
1081   if (!src_argb || !dst_yuy2 || width <= 0 || height == 0) {
1082     return -1;
1083   }
1084   // Negative height means invert the image.
1085   if (height < 0) {
1086     height = -height;
1087     dst_yuy2 = dst_yuy2 + (height - 1) * dst_stride_yuy2;
1088     dst_stride_yuy2 = -dst_stride_yuy2;
1089   }
1090   // Coalesce rows.
1091   if (src_stride_argb == width * 4 && dst_stride_yuy2 == width * 2) {
1092     width *= height;
1093     height = 1;
1094     src_stride_argb = dst_stride_yuy2 = 0;
1095   }
1096 #if defined(HAS_ARGBTOYROW_SSSE3)
1097   if (TestCpuFlag(kCpuHasSSSE3)) {
1098     ARGBToYRow = ARGBToYRow_Any_SSSE3;
1099     if (IS_ALIGNED(width, 16)) {
1100       ARGBToYRow = ARGBToYRow_SSSE3;
1101     }
1102   }
1103 #endif
1104 #if defined(HAS_ARGBTOUVROW_SSSE3)
1105   if (TestCpuFlag(kCpuHasSSSE3)) {
1106     ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
1107     if (IS_ALIGNED(width, 16)) {
1108       ARGBToUVRow = ARGBToUVRow_SSSE3;
1109     }
1110   }
1111 #endif
1112 #if defined(HAS_ARGBTOYROW_AVX2)
1113   if (TestCpuFlag(kCpuHasAVX2)) {
1114     ARGBToYRow = ARGBToYRow_Any_AVX2;
1115     if (IS_ALIGNED(width, 32)) {
1116       ARGBToYRow = ARGBToYRow_AVX2;
1117     }
1118   }
1119 #endif
1120 #if defined(HAS_ARGBTOUVROW_AVX2)
1121   if (TestCpuFlag(kCpuHasAVX2)) {
1122     ARGBToUVRow = ARGBToUVRow_Any_AVX2;
1123     if (IS_ALIGNED(width, 32)) {
1124       ARGBToUVRow = ARGBToUVRow_AVX2;
1125     }
1126   }
1127 #endif
1128 #if defined(HAS_ARGBTOYROW_NEON)
1129   if (TestCpuFlag(kCpuHasNEON)) {
1130     ARGBToYRow = ARGBToYRow_Any_NEON;
1131     if (IS_ALIGNED(width, 16)) {
1132       ARGBToYRow = ARGBToYRow_NEON;
1133     }
1134   }
1135 #endif
1136 #if defined(HAS_ARGBTOUVROW_NEON)
1137   if (TestCpuFlag(kCpuHasNEON)) {
1138     ARGBToUVRow = ARGBToUVRow_Any_NEON;
1139     if (IS_ALIGNED(width, 16)) {
1140       ARGBToUVRow = ARGBToUVRow_NEON;
1141     }
1142   }
1143 #endif
1144 #if defined(HAS_ARGBTOYROW_MSA) && defined(HAS_ARGBTOUVROW_MSA)
1145   if (TestCpuFlag(kCpuHasMSA)) {
1146     ARGBToYRow = ARGBToYRow_Any_MSA;
1147     ARGBToUVRow = ARGBToUVRow_Any_MSA;
1148     if (IS_ALIGNED(width, 16)) {
1149       ARGBToYRow = ARGBToYRow_MSA;
1150     }
1151     if (IS_ALIGNED(width, 32)) {
1152       ARGBToUVRow = ARGBToUVRow_MSA;
1153     }
1154   }
1155 #endif
1156 #if defined(HAS_ARGBTOYROW_LSX)
1157   if (TestCpuFlag(kCpuHasLSX)) {
1158     ARGBToYRow = ARGBToYRow_Any_LSX;
1159     if (IS_ALIGNED(width, 16)) {
1160       ARGBToYRow = ARGBToYRow_LSX;
1161     }
1162   }
1163 #endif
1164 #if defined(HAS_ARGBTOYROW_LSX) && defined(HAS_ARGBTOUVROW_LSX)
1165   if (TestCpuFlag(kCpuHasLSX)) {
1166     ARGBToYRow = ARGBToYRow_Any_LSX;
1167     ARGBToUVRow = ARGBToUVRow_Any_LSX;
1168     if (IS_ALIGNED(width, 16)) {
1169       ARGBToYRow = ARGBToYRow_LSX;
1170       ARGBToUVRow = ARGBToUVRow_LSX;
1171     }
1172   }
1173 #endif
1174 #if defined(HAS_ARGBTOYROW_LASX) && defined(HAS_ARGBTOUVROW_LASX)
1175   if (TestCpuFlag(kCpuHasLASX)) {
1176     ARGBToYRow = ARGBToYRow_Any_LASX;
1177     ARGBToUVRow = ARGBToUVRow_Any_LASX;
1178     if (IS_ALIGNED(width, 32)) {
1179       ARGBToYRow = ARGBToYRow_LASX;
1180       ARGBToUVRow = ARGBToUVRow_LASX;
1181     }
1182   }
1183 #endif
1184 #if defined(HAS_ARGBTOYROW_RVV)
1185   if (TestCpuFlag(kCpuHasRVV)) {
1186     ARGBToYRow = ARGBToYRow_RVV;
1187   }
1188 #endif
1189 #if defined(HAS_I422TOYUY2ROW_SSE2)
1190   if (TestCpuFlag(kCpuHasSSE2)) {
1191     I422ToYUY2Row = I422ToYUY2Row_Any_SSE2;
1192     if (IS_ALIGNED(width, 16)) {
1193       I422ToYUY2Row = I422ToYUY2Row_SSE2;
1194     }
1195   }
1196 #endif
1197 #if defined(HAS_I422TOYUY2ROW_AVX2)
1198   if (TestCpuFlag(kCpuHasAVX2)) {
1199     I422ToYUY2Row = I422ToYUY2Row_Any_AVX2;
1200     if (IS_ALIGNED(width, 32)) {
1201       I422ToYUY2Row = I422ToYUY2Row_AVX2;
1202     }
1203   }
1204 #endif
1205 #if defined(HAS_I422TOYUY2ROW_NEON)
1206   if (TestCpuFlag(kCpuHasNEON)) {
1207     I422ToYUY2Row = I422ToYUY2Row_Any_NEON;
1208     if (IS_ALIGNED(width, 16)) {
1209       I422ToYUY2Row = I422ToYUY2Row_NEON;
1210     }
1211   }
1212 #endif
1213 #if defined(HAS_I422TOYUY2ROW_MSA)
1214   if (TestCpuFlag(kCpuHasMSA)) {
1215     I422ToYUY2Row = I422ToYUY2Row_Any_MSA;
1216     if (IS_ALIGNED(width, 32)) {
1217       I422ToYUY2Row = I422ToYUY2Row_MSA;
1218     }
1219   }
1220 #endif
1221 #if defined(HAS_I422TOYUY2ROW_LSX)
1222   if (TestCpuFlag(kCpuHasLSX)) {
1223     I422ToYUY2Row = I422ToYUY2Row_Any_LSX;
1224     if (IS_ALIGNED(width, 16)) {
1225       I422ToYUY2Row = I422ToYUY2Row_LSX;
1226     }
1227   }
1228 #endif
1229 #if defined(HAS_I422TOYUY2ROW_LASX)
1230   if (TestCpuFlag(kCpuHasLASX)) {
1231     I422ToYUY2Row = I422ToYUY2Row_Any_LASX;
1232     if (IS_ALIGNED(width, 32)) {
1233       I422ToYUY2Row = I422ToYUY2Row_LASX;
1234     }
1235   }
1236 #endif
1237 
1238   {
1239     // Allocate a rows of yuv.
1240     align_buffer_64(row_y, ((width + 63) & ~63) * 2);
1241     uint8_t* row_u = row_y + ((width + 63) & ~63);
1242     uint8_t* row_v = row_u + ((width + 63) & ~63) / 2;
1243     if (!row_y)
1244       return 1;
1245 
1246     for (y = 0; y < height; ++y) {
1247       ARGBToUVRow(src_argb, 0, row_u, row_v, width);
1248       ARGBToYRow(src_argb, row_y, width);
1249       I422ToYUY2Row(row_y, row_u, row_v, dst_yuy2, width);
1250       src_argb += src_stride_argb;
1251       dst_yuy2 += dst_stride_yuy2;
1252     }
1253 
1254     free_aligned_buffer_64(row_y);
1255   }
1256   return 0;
1257 }
1258 
1259 // Convert ARGB to UYVY.
1260 LIBYUV_API
ARGBToUYVY(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_uyvy,int dst_stride_uyvy,int width,int height)1261 int ARGBToUYVY(const uint8_t* src_argb,
1262                int src_stride_argb,
1263                uint8_t* dst_uyvy,
1264                int dst_stride_uyvy,
1265                int width,
1266                int height) {
1267   int y;
1268   void (*ARGBToUVRow)(const uint8_t* src_argb, int src_stride_argb,
1269                       uint8_t* dst_u, uint8_t* dst_v, int width) =
1270       ARGBToUVRow_C;
1271   void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
1272       ARGBToYRow_C;
1273   void (*I422ToUYVYRow)(const uint8_t* src_y, const uint8_t* src_u,
1274                         const uint8_t* src_v, uint8_t* dst_uyvy, int width) =
1275       I422ToUYVYRow_C;
1276 
1277   if (!src_argb || !dst_uyvy || width <= 0 || height == 0) {
1278     return -1;
1279   }
1280   // Negative height means invert the image.
1281   if (height < 0) {
1282     height = -height;
1283     dst_uyvy = dst_uyvy + (height - 1) * dst_stride_uyvy;
1284     dst_stride_uyvy = -dst_stride_uyvy;
1285   }
1286   // Coalesce rows.
1287   if (src_stride_argb == width * 4 && dst_stride_uyvy == width * 2) {
1288     width *= height;
1289     height = 1;
1290     src_stride_argb = dst_stride_uyvy = 0;
1291   }
1292 #if defined(HAS_ARGBTOYROW_SSSE3)
1293   if (TestCpuFlag(kCpuHasSSSE3)) {
1294     ARGBToYRow = ARGBToYRow_Any_SSSE3;
1295     if (IS_ALIGNED(width, 16)) {
1296       ARGBToYRow = ARGBToYRow_SSSE3;
1297     }
1298   }
1299 #endif
1300 #if defined(HAS_ARGBTOUVROW_SSSE3)
1301   if (TestCpuFlag(kCpuHasSSSE3)) {
1302     ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
1303     if (IS_ALIGNED(width, 16)) {
1304       ARGBToUVRow = ARGBToUVRow_SSSE3;
1305     }
1306   }
1307 #endif
1308 #if defined(HAS_ARGBTOYROW_AVX2)
1309   if (TestCpuFlag(kCpuHasAVX2)) {
1310     ARGBToYRow = ARGBToYRow_Any_AVX2;
1311     if (IS_ALIGNED(width, 32)) {
1312       ARGBToYRow = ARGBToYRow_AVX2;
1313     }
1314   }
1315 #endif
1316 #if defined(HAS_ARGBTOUVROW_AVX2)
1317   if (TestCpuFlag(kCpuHasAVX2)) {
1318     ARGBToUVRow = ARGBToUVRow_Any_AVX2;
1319     if (IS_ALIGNED(width, 32)) {
1320       ARGBToUVRow = ARGBToUVRow_AVX2;
1321     }
1322   }
1323 #endif
1324 #if defined(HAS_ARGBTOYROW_NEON)
1325   if (TestCpuFlag(kCpuHasNEON)) {
1326     ARGBToYRow = ARGBToYRow_Any_NEON;
1327     if (IS_ALIGNED(width, 16)) {
1328       ARGBToYRow = ARGBToYRow_NEON;
1329     }
1330   }
1331 #endif
1332 #if defined(HAS_ARGBTOUVROW_NEON)
1333   if (TestCpuFlag(kCpuHasNEON)) {
1334     ARGBToUVRow = ARGBToUVRow_Any_NEON;
1335     if (IS_ALIGNED(width, 16)) {
1336       ARGBToUVRow = ARGBToUVRow_NEON;
1337     }
1338   }
1339 #endif
1340 #if defined(HAS_ARGBTOYROW_MSA) && defined(HAS_ARGBTOUVROW_MSA)
1341   if (TestCpuFlag(kCpuHasMSA)) {
1342     ARGBToYRow = ARGBToYRow_Any_MSA;
1343     ARGBToUVRow = ARGBToUVRow_Any_MSA;
1344     if (IS_ALIGNED(width, 16)) {
1345       ARGBToYRow = ARGBToYRow_MSA;
1346     }
1347     if (IS_ALIGNED(width, 32)) {
1348       ARGBToUVRow = ARGBToUVRow_MSA;
1349     }
1350   }
1351 #endif
1352 #if defined(HAS_ARGBTOYROW_LSX)
1353   if (TestCpuFlag(kCpuHasLSX)) {
1354     ARGBToYRow = ARGBToYRow_Any_LSX;
1355     if (IS_ALIGNED(width, 16)) {
1356       ARGBToYRow = ARGBToYRow_LSX;
1357     }
1358   }
1359 #endif
1360 #if defined(HAS_ARGBTOYROW_LSX) && defined(HAS_ARGBTOUVROW_LSX)
1361   if (TestCpuFlag(kCpuHasLSX)) {
1362     ARGBToYRow = ARGBToYRow_Any_LSX;
1363     ARGBToUVRow = ARGBToUVRow_Any_LSX;
1364     if (IS_ALIGNED(width, 16)) {
1365       ARGBToYRow = ARGBToYRow_LSX;
1366       ARGBToUVRow = ARGBToUVRow_LSX;
1367     }
1368   }
1369 #endif
1370 #if defined(HAS_ARGBTOYROW_LASX) && defined(HAS_ARGBTOUVROW_LASX)
1371   if (TestCpuFlag(kCpuHasLASX)) {
1372     ARGBToYRow = ARGBToYRow_Any_LASX;
1373     ARGBToUVRow = ARGBToUVRow_Any_LASX;
1374     if (IS_ALIGNED(width, 32)) {
1375       ARGBToYRow = ARGBToYRow_LASX;
1376       ARGBToUVRow = ARGBToUVRow_LASX;
1377     }
1378   }
1379 #endif
1380 #if defined(HAS_ARGBTOYROW_RVV)
1381   if (TestCpuFlag(kCpuHasRVV)) {
1382     ARGBToYRow = ARGBToYRow_RVV;
1383   }
1384 #endif
1385 #if defined(HAS_I422TOUYVYROW_SSE2)
1386   if (TestCpuFlag(kCpuHasSSE2)) {
1387     I422ToUYVYRow = I422ToUYVYRow_Any_SSE2;
1388     if (IS_ALIGNED(width, 16)) {
1389       I422ToUYVYRow = I422ToUYVYRow_SSE2;
1390     }
1391   }
1392 #endif
1393 #if defined(HAS_I422TOUYVYROW_AVX2)
1394   if (TestCpuFlag(kCpuHasAVX2)) {
1395     I422ToUYVYRow = I422ToUYVYRow_Any_AVX2;
1396     if (IS_ALIGNED(width, 32)) {
1397       I422ToUYVYRow = I422ToUYVYRow_AVX2;
1398     }
1399   }
1400 #endif
1401 #if defined(HAS_I422TOUYVYROW_NEON)
1402   if (TestCpuFlag(kCpuHasNEON)) {
1403     I422ToUYVYRow = I422ToUYVYRow_Any_NEON;
1404     if (IS_ALIGNED(width, 16)) {
1405       I422ToUYVYRow = I422ToUYVYRow_NEON;
1406     }
1407   }
1408 #endif
1409 #if defined(HAS_I422TOUYVYROW_MSA)
1410   if (TestCpuFlag(kCpuHasMSA)) {
1411     I422ToUYVYRow = I422ToUYVYRow_Any_MSA;
1412     if (IS_ALIGNED(width, 32)) {
1413       I422ToUYVYRow = I422ToUYVYRow_MSA;
1414     }
1415   }
1416 #endif
1417 #if defined(HAS_I422TOUYVYROW_LSX)
1418   if (TestCpuFlag(kCpuHasLSX)) {
1419     I422ToUYVYRow = I422ToUYVYRow_Any_LSX;
1420     if (IS_ALIGNED(width, 16)) {
1421       I422ToUYVYRow = I422ToUYVYRow_LSX;
1422     }
1423   }
1424 #endif
1425 #if defined(HAS_I422TOUYVYROW_LASX)
1426   if (TestCpuFlag(kCpuHasLASX)) {
1427     I422ToUYVYRow = I422ToUYVYRow_Any_LASX;
1428     if (IS_ALIGNED(width, 32)) {
1429       I422ToUYVYRow = I422ToUYVYRow_LASX;
1430     }
1431   }
1432 #endif
1433 
1434   {
1435     // Allocate a rows of yuv.
1436     align_buffer_64(row_y, ((width + 63) & ~63) * 2);
1437     uint8_t* row_u = row_y + ((width + 63) & ~63);
1438     uint8_t* row_v = row_u + ((width + 63) & ~63) / 2;
1439     if (!row_y)
1440       return 1;
1441 
1442     for (y = 0; y < height; ++y) {
1443       ARGBToUVRow(src_argb, 0, row_u, row_v, width);
1444       ARGBToYRow(src_argb, row_y, width);
1445       I422ToUYVYRow(row_y, row_u, row_v, dst_uyvy, width);
1446       src_argb += src_stride_argb;
1447       dst_uyvy += dst_stride_uyvy;
1448     }
1449 
1450     free_aligned_buffer_64(row_y);
1451   }
1452   return 0;
1453 }
1454 
1455 // Convert ARGB to I400.
1456 LIBYUV_API
ARGBToI400(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_y,int dst_stride_y,int width,int height)1457 int ARGBToI400(const uint8_t* src_argb,
1458                int src_stride_argb,
1459                uint8_t* dst_y,
1460                int dst_stride_y,
1461                int width,
1462                int height) {
1463   int y;
1464   void (*ARGBToYRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
1465       ARGBToYRow_C;
1466   if (!src_argb || !dst_y || width <= 0 || height == 0) {
1467     return -1;
1468   }
1469   if (height < 0) {
1470     height = -height;
1471     src_argb = src_argb + (height - 1) * src_stride_argb;
1472     src_stride_argb = -src_stride_argb;
1473   }
1474   // Coalesce rows.
1475   if (src_stride_argb == width * 4 && dst_stride_y == width) {
1476     width *= height;
1477     height = 1;
1478     src_stride_argb = dst_stride_y = 0;
1479   }
1480 #if defined(HAS_ARGBTOYROW_SSSE3)
1481   if (TestCpuFlag(kCpuHasSSSE3)) {
1482     ARGBToYRow = ARGBToYRow_Any_SSSE3;
1483     if (IS_ALIGNED(width, 16)) {
1484       ARGBToYRow = ARGBToYRow_SSSE3;
1485     }
1486   }
1487 #endif
1488 #if defined(HAS_ARGBTOYROW_AVX2)
1489   if (TestCpuFlag(kCpuHasAVX2)) {
1490     ARGBToYRow = ARGBToYRow_Any_AVX2;
1491     if (IS_ALIGNED(width, 32)) {
1492       ARGBToYRow = ARGBToYRow_AVX2;
1493     }
1494   }
1495 #endif
1496 #if defined(HAS_ARGBTOYROW_NEON)
1497   if (TestCpuFlag(kCpuHasNEON)) {
1498     ARGBToYRow = ARGBToYRow_Any_NEON;
1499     if (IS_ALIGNED(width, 16)) {
1500       ARGBToYRow = ARGBToYRow_NEON;
1501     }
1502   }
1503 #endif
1504 #if defined(HAS_ARGBTOYROW_MSA)
1505   if (TestCpuFlag(kCpuHasMSA)) {
1506     ARGBToYRow = ARGBToYRow_Any_MSA;
1507     if (IS_ALIGNED(width, 16)) {
1508       ARGBToYRow = ARGBToYRow_MSA;
1509     }
1510   }
1511 #endif
1512 #if defined(HAS_ARGBTOYROW_LSX)
1513   if (TestCpuFlag(kCpuHasLSX)) {
1514     ARGBToYRow = ARGBToYRow_Any_LSX;
1515     if (IS_ALIGNED(width, 16)) {
1516       ARGBToYRow = ARGBToYRow_LSX;
1517     }
1518   }
1519 #endif
1520 #if defined(HAS_ARGBTOYROW_LASX)
1521   if (TestCpuFlag(kCpuHasLASX)) {
1522     ARGBToYRow = ARGBToYRow_Any_LASX;
1523     if (IS_ALIGNED(width, 32)) {
1524       ARGBToYRow = ARGBToYRow_LASX;
1525     }
1526   }
1527 #endif
1528 #if defined(HAS_ARGBTOYROW_RVV)
1529   if (TestCpuFlag(kCpuHasRVV)) {
1530     ARGBToYRow = ARGBToYRow_RVV;
1531   }
1532 #endif
1533 
1534   for (y = 0; y < height; ++y) {
1535     ARGBToYRow(src_argb, dst_y, width);
1536     src_argb += src_stride_argb;
1537     dst_y += dst_stride_y;
1538   }
1539   return 0;
1540 }
1541 
1542 #ifndef __riscv
1543 // Shuffle table for converting ARGB to RGBA.
1544 static const uvec8 kShuffleMaskARGBToRGBA = {
1545     3u, 0u, 1u, 2u, 7u, 4u, 5u, 6u, 11u, 8u, 9u, 10u, 15u, 12u, 13u, 14u};
1546 
1547 // Convert ARGB to RGBA.
1548 LIBYUV_API
ARGBToRGBA(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_rgba,int dst_stride_rgba,int width,int height)1549 int ARGBToRGBA(const uint8_t* src_argb,
1550                int src_stride_argb,
1551                uint8_t* dst_rgba,
1552                int dst_stride_rgba,
1553                int width,
1554                int height) {
1555   return ARGBShuffle(src_argb, src_stride_argb, dst_rgba, dst_stride_rgba,
1556                      (const uint8_t*)(&kShuffleMaskARGBToRGBA), width, height);
1557 }
1558 #else
1559 // Convert ARGB to RGBA.
1560 LIBYUV_API
ARGBToRGBA(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_rgba,int dst_stride_rgba,int width,int height)1561 int ARGBToRGBA(const uint8_t* src_argb,
1562                int src_stride_argb,
1563                uint8_t* dst_rgba,
1564                int dst_stride_rgba,
1565                int width,
1566                int height) {
1567   int y;
1568   void (*ARGBToRGBARow)(const uint8_t* src_argb, uint8_t* dst_rgba, int width) =
1569       ARGBToRGBARow_C;
1570   if (!src_argb || !dst_rgba || width <= 0 || height == 0) {
1571     return -1;
1572   }
1573   if (height < 0) {
1574     height = -height;
1575     src_argb = src_argb + (height - 1) * src_stride_argb;
1576     src_stride_argb = -src_stride_argb;
1577   }
1578   // Coalesce rows.
1579   if (src_stride_argb == width * 4 && dst_stride_rgba == width * 4) {
1580     width *= height;
1581     height = 1;
1582     src_stride_argb = dst_stride_rgba = 0;
1583   }
1584 
1585 #if defined(HAS_ARGBTORGBAROW_RVV)
1586   if (TestCpuFlag(kCpuHasRVV)) {
1587     ARGBToRGBARow = ARGBToRGBARow_RVV;
1588   }
1589 #endif
1590 
1591   for (y = 0; y < height; ++y) {
1592     ARGBToRGBARow(src_argb, dst_rgba, width);
1593     src_argb += src_stride_argb;
1594     dst_rgba += dst_stride_rgba;
1595   }
1596   return 0;
1597 }
1598 #endif
1599 
1600 // Convert ARGB To RGB24.
1601 LIBYUV_API
ARGBToRGB24(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_rgb24,int dst_stride_rgb24,int width,int height)1602 int ARGBToRGB24(const uint8_t* src_argb,
1603                 int src_stride_argb,
1604                 uint8_t* dst_rgb24,
1605                 int dst_stride_rgb24,
1606                 int width,
1607                 int height) {
1608   int y;
1609   void (*ARGBToRGB24Row)(const uint8_t* src_argb, uint8_t* dst_rgb, int width) =
1610       ARGBToRGB24Row_C;
1611   if (!src_argb || !dst_rgb24 || width <= 0 || height == 0) {
1612     return -1;
1613   }
1614   if (height < 0) {
1615     height = -height;
1616     src_argb = src_argb + (height - 1) * src_stride_argb;
1617     src_stride_argb = -src_stride_argb;
1618   }
1619   // Coalesce rows.
1620   if (src_stride_argb == width * 4 && dst_stride_rgb24 == width * 3) {
1621     width *= height;
1622     height = 1;
1623     src_stride_argb = dst_stride_rgb24 = 0;
1624   }
1625 #if defined(HAS_ARGBTORGB24ROW_SSSE3)
1626   if (TestCpuFlag(kCpuHasSSSE3)) {
1627     ARGBToRGB24Row = ARGBToRGB24Row_Any_SSSE3;
1628     if (IS_ALIGNED(width, 16)) {
1629       ARGBToRGB24Row = ARGBToRGB24Row_SSSE3;
1630     }
1631   }
1632 #endif
1633 #if defined(HAS_ARGBTORGB24ROW_AVX2)
1634   if (TestCpuFlag(kCpuHasAVX2)) {
1635     ARGBToRGB24Row = ARGBToRGB24Row_Any_AVX2;
1636     if (IS_ALIGNED(width, 32)) {
1637       ARGBToRGB24Row = ARGBToRGB24Row_AVX2;
1638     }
1639   }
1640 #endif
1641 #if defined(HAS_ARGBTORGB24ROW_AVX512VBMI)
1642   if (TestCpuFlag(kCpuHasAVX512VBMI)) {
1643     ARGBToRGB24Row = ARGBToRGB24Row_Any_AVX512VBMI;
1644     if (IS_ALIGNED(width, 32)) {
1645       ARGBToRGB24Row = ARGBToRGB24Row_AVX512VBMI;
1646     }
1647   }
1648 #endif
1649 #if defined(HAS_ARGBTORGB24ROW_NEON)
1650   if (TestCpuFlag(kCpuHasNEON)) {
1651     ARGBToRGB24Row = ARGBToRGB24Row_Any_NEON;
1652     if (IS_ALIGNED(width, 16)) {
1653       ARGBToRGB24Row = ARGBToRGB24Row_NEON;
1654     }
1655   }
1656 #endif
1657 #if defined(HAS_ARGBTORGB24ROW_MSA)
1658   if (TestCpuFlag(kCpuHasMSA)) {
1659     ARGBToRGB24Row = ARGBToRGB24Row_Any_MSA;
1660     if (IS_ALIGNED(width, 16)) {
1661       ARGBToRGB24Row = ARGBToRGB24Row_MSA;
1662     }
1663   }
1664 #endif
1665 #if defined(HAS_ARGBTORGB24ROW_LSX)
1666   if (TestCpuFlag(kCpuHasLSX)) {
1667     ARGBToRGB24Row = ARGBToRGB24Row_Any_LSX;
1668     if (IS_ALIGNED(width, 16)) {
1669       ARGBToRGB24Row = ARGBToRGB24Row_LSX;
1670     }
1671   }
1672 #endif
1673 #if defined(HAS_ARGBTORGB24ROW_LASX)
1674   if (TestCpuFlag(kCpuHasLASX)) {
1675     ARGBToRGB24Row = ARGBToRGB24Row_Any_LASX;
1676     if (IS_ALIGNED(width, 32)) {
1677       ARGBToRGB24Row = ARGBToRGB24Row_LASX;
1678     }
1679   }
1680 #endif
1681 #if defined(HAS_ARGBTORGB24ROW_RVV)
1682   if (TestCpuFlag(kCpuHasRVV)) {
1683     ARGBToRGB24Row = ARGBToRGB24Row_RVV;
1684   }
1685 #endif
1686 
1687   for (y = 0; y < height; ++y) {
1688     ARGBToRGB24Row(src_argb, dst_rgb24, width);
1689     src_argb += src_stride_argb;
1690     dst_rgb24 += dst_stride_rgb24;
1691   }
1692   return 0;
1693 }
1694 
1695 // Convert ARGB To RAW.
1696 LIBYUV_API
ARGBToRAW(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_raw,int dst_stride_raw,int width,int height)1697 int ARGBToRAW(const uint8_t* src_argb,
1698               int src_stride_argb,
1699               uint8_t* dst_raw,
1700               int dst_stride_raw,
1701               int width,
1702               int height) {
1703   int y;
1704   void (*ARGBToRAWRow)(const uint8_t* src_argb, uint8_t* dst_rgb, int width) =
1705       ARGBToRAWRow_C;
1706   if (!src_argb || !dst_raw || width <= 0 || height == 0) {
1707     return -1;
1708   }
1709   if (height < 0) {
1710     height = -height;
1711     src_argb = src_argb + (height - 1) * src_stride_argb;
1712     src_stride_argb = -src_stride_argb;
1713   }
1714   // Coalesce rows.
1715   if (src_stride_argb == width * 4 && dst_stride_raw == width * 3) {
1716     width *= height;
1717     height = 1;
1718     src_stride_argb = dst_stride_raw = 0;
1719   }
1720 #if defined(HAS_ARGBTORAWROW_SSSE3)
1721   if (TestCpuFlag(kCpuHasSSSE3)) {
1722     ARGBToRAWRow = ARGBToRAWRow_Any_SSSE3;
1723     if (IS_ALIGNED(width, 16)) {
1724       ARGBToRAWRow = ARGBToRAWRow_SSSE3;
1725     }
1726   }
1727 #endif
1728 #if defined(HAS_ARGBTORAWROW_AVX2)
1729   if (TestCpuFlag(kCpuHasAVX2)) {
1730     ARGBToRAWRow = ARGBToRAWRow_Any_AVX2;
1731     if (IS_ALIGNED(width, 32)) {
1732       ARGBToRAWRow = ARGBToRAWRow_AVX2;
1733     }
1734   }
1735 #endif
1736 #if defined(HAS_ARGBTORAWROW_NEON)
1737   if (TestCpuFlag(kCpuHasNEON)) {
1738     ARGBToRAWRow = ARGBToRAWRow_Any_NEON;
1739     if (IS_ALIGNED(width, 8)) {
1740       ARGBToRAWRow = ARGBToRAWRow_NEON;
1741     }
1742   }
1743 #endif
1744 #if defined(HAS_ARGBTORAWROW_MSA)
1745   if (TestCpuFlag(kCpuHasMSA)) {
1746     ARGBToRAWRow = ARGBToRAWRow_Any_MSA;
1747     if (IS_ALIGNED(width, 16)) {
1748       ARGBToRAWRow = ARGBToRAWRow_MSA;
1749     }
1750   }
1751 #endif
1752 #if defined(HAS_ARGBTORAWROW_LSX)
1753   if (TestCpuFlag(kCpuHasLSX)) {
1754     ARGBToRAWRow = ARGBToRAWRow_Any_LSX;
1755     if (IS_ALIGNED(width, 16)) {
1756       ARGBToRAWRow = ARGBToRAWRow_LSX;
1757     }
1758   }
1759 #endif
1760 #if defined(HAS_ARGBTORAWROW_LASX)
1761   if (TestCpuFlag(kCpuHasLASX)) {
1762     ARGBToRAWRow = ARGBToRAWRow_Any_LASX;
1763     if (IS_ALIGNED(width, 32)) {
1764       ARGBToRAWRow = ARGBToRAWRow_LASX;
1765     }
1766   }
1767 #endif
1768 #if defined(HAS_ARGBTORAWROW_RVV)
1769   if (TestCpuFlag(kCpuHasRVV)) {
1770     ARGBToRAWRow = ARGBToRAWRow_RVV;
1771   }
1772 #endif
1773 
1774   for (y = 0; y < height; ++y) {
1775     ARGBToRAWRow(src_argb, dst_raw, width);
1776     src_argb += src_stride_argb;
1777     dst_raw += dst_stride_raw;
1778   }
1779   return 0;
1780 }
1781 
1782 // Ordered 8x8 dither for 888 to 565.  Values from 0 to 7.
1783 static const uint8_t kDither565_4x4[16] = {
1784     0, 4, 1, 5, 6, 2, 7, 3, 1, 5, 0, 4, 7, 3, 6, 2,
1785 };
1786 
1787 // Convert ARGB To RGB565 with 4x4 dither matrix (16 bytes).
1788 LIBYUV_API
ARGBToRGB565Dither(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_rgb565,int dst_stride_rgb565,const uint8_t * dither4x4,int width,int height)1789 int ARGBToRGB565Dither(const uint8_t* src_argb,
1790                        int src_stride_argb,
1791                        uint8_t* dst_rgb565,
1792                        int dst_stride_rgb565,
1793                        const uint8_t* dither4x4,
1794                        int width,
1795                        int height) {
1796   int y;
1797   void (*ARGBToRGB565DitherRow)(const uint8_t* src_argb, uint8_t* dst_rgb,
1798                                 uint32_t dither4, int width) =
1799       ARGBToRGB565DitherRow_C;
1800   if (!src_argb || !dst_rgb565 || width <= 0 || height == 0) {
1801     return -1;
1802   }
1803   if (height < 0) {
1804     height = -height;
1805     src_argb = src_argb + (height - 1) * src_stride_argb;
1806     src_stride_argb = -src_stride_argb;
1807   }
1808   if (!dither4x4) {
1809     dither4x4 = kDither565_4x4;
1810   }
1811 #if defined(HAS_ARGBTORGB565DITHERROW_SSE2)
1812   if (TestCpuFlag(kCpuHasSSE2)) {
1813     ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_SSE2;
1814     if (IS_ALIGNED(width, 4)) {
1815       ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_SSE2;
1816     }
1817   }
1818 #endif
1819 #if defined(HAS_ARGBTORGB565DITHERROW_AVX2)
1820   if (TestCpuFlag(kCpuHasAVX2)) {
1821     ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_AVX2;
1822     if (IS_ALIGNED(width, 8)) {
1823       ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_AVX2;
1824     }
1825   }
1826 #endif
1827 #if defined(HAS_ARGBTORGB565DITHERROW_NEON)
1828   if (TestCpuFlag(kCpuHasNEON)) {
1829     ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_NEON;
1830     if (IS_ALIGNED(width, 8)) {
1831       ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_NEON;
1832     }
1833   }
1834 #endif
1835 #if defined(HAS_ARGBTORGB565DITHERROW_MSA)
1836   if (TestCpuFlag(kCpuHasMSA)) {
1837     ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_MSA;
1838     if (IS_ALIGNED(width, 8)) {
1839       ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_MSA;
1840     }
1841   }
1842 #endif
1843 #if defined(HAS_ARGBTORGB565DITHERROW_LSX)
1844   if (TestCpuFlag(kCpuHasLSX)) {
1845     ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_LSX;
1846     if (IS_ALIGNED(width, 8)) {
1847       ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_LSX;
1848     }
1849   }
1850 #endif
1851 #if defined(HAS_ARGBTORGB565DITHERROW_LASX)
1852   if (TestCpuFlag(kCpuHasLASX)) {
1853     ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_LASX;
1854     if (IS_ALIGNED(width, 16)) {
1855       ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_LASX;
1856     }
1857   }
1858 #endif
1859 
1860   for (y = 0; y < height; ++y) {
1861     ARGBToRGB565DitherRow(src_argb, dst_rgb565,
1862                           *(const uint32_t*)(dither4x4 + ((y & 3) << 2)),
1863                           width);
1864     src_argb += src_stride_argb;
1865     dst_rgb565 += dst_stride_rgb565;
1866   }
1867   return 0;
1868 }
1869 
1870 // Convert ARGB To RGB565.
1871 // TODO(fbarchard): Consider using dither function low level with zeros.
1872 LIBYUV_API
ARGBToRGB565(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_rgb565,int dst_stride_rgb565,int width,int height)1873 int ARGBToRGB565(const uint8_t* src_argb,
1874                  int src_stride_argb,
1875                  uint8_t* dst_rgb565,
1876                  int dst_stride_rgb565,
1877                  int width,
1878                  int height) {
1879   int y;
1880   void (*ARGBToRGB565Row)(const uint8_t* src_argb, uint8_t* dst_rgb,
1881                           int width) = ARGBToRGB565Row_C;
1882   if (!src_argb || !dst_rgb565 || width <= 0 || height == 0) {
1883     return -1;
1884   }
1885   if (height < 0) {
1886     height = -height;
1887     src_argb = src_argb + (height - 1) * src_stride_argb;
1888     src_stride_argb = -src_stride_argb;
1889   }
1890   // Coalesce rows.
1891   if (src_stride_argb == width * 4 && dst_stride_rgb565 == width * 2) {
1892     width *= height;
1893     height = 1;
1894     src_stride_argb = dst_stride_rgb565 = 0;
1895   }
1896 #if defined(HAS_ARGBTORGB565ROW_SSE2)
1897   if (TestCpuFlag(kCpuHasSSE2)) {
1898     ARGBToRGB565Row = ARGBToRGB565Row_Any_SSE2;
1899     if (IS_ALIGNED(width, 4)) {
1900       ARGBToRGB565Row = ARGBToRGB565Row_SSE2;
1901     }
1902   }
1903 #endif
1904 #if defined(HAS_ARGBTORGB565ROW_AVX2)
1905   if (TestCpuFlag(kCpuHasAVX2)) {
1906     ARGBToRGB565Row = ARGBToRGB565Row_Any_AVX2;
1907     if (IS_ALIGNED(width, 8)) {
1908       ARGBToRGB565Row = ARGBToRGB565Row_AVX2;
1909     }
1910   }
1911 #endif
1912 #if defined(HAS_ARGBTORGB565ROW_NEON)
1913   if (TestCpuFlag(kCpuHasNEON)) {
1914     ARGBToRGB565Row = ARGBToRGB565Row_Any_NEON;
1915     if (IS_ALIGNED(width, 8)) {
1916       ARGBToRGB565Row = ARGBToRGB565Row_NEON;
1917     }
1918   }
1919 #endif
1920 #if defined(HAS_ARGBTORGB565ROW_MSA)
1921   if (TestCpuFlag(kCpuHasMSA)) {
1922     ARGBToRGB565Row = ARGBToRGB565Row_Any_MSA;
1923     if (IS_ALIGNED(width, 8)) {
1924       ARGBToRGB565Row = ARGBToRGB565Row_MSA;
1925     }
1926   }
1927 #endif
1928 #if defined(HAS_ARGBTORGB565ROW_LSX)
1929   if (TestCpuFlag(kCpuHasLSX)) {
1930     ARGBToRGB565Row = ARGBToRGB565Row_Any_LSX;
1931     if (IS_ALIGNED(width, 8)) {
1932       ARGBToRGB565Row = ARGBToRGB565Row_LSX;
1933     }
1934   }
1935 #endif
1936 
1937 #if defined(HAS_ARGBTORGB565ROW_LASX)
1938   if (TestCpuFlag(kCpuHasLASX)) {
1939     ARGBToRGB565Row = ARGBToRGB565Row_Any_LASX;
1940     if (IS_ALIGNED(width, 16)) {
1941       ARGBToRGB565Row = ARGBToRGB565Row_LASX;
1942     }
1943   }
1944 #endif
1945 
1946   for (y = 0; y < height; ++y) {
1947     ARGBToRGB565Row(src_argb, dst_rgb565, width);
1948     src_argb += src_stride_argb;
1949     dst_rgb565 += dst_stride_rgb565;
1950   }
1951   return 0;
1952 }
1953 
1954 // Convert ARGB To ARGB1555.
1955 LIBYUV_API
ARGBToARGB1555(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_argb1555,int dst_stride_argb1555,int width,int height)1956 int ARGBToARGB1555(const uint8_t* src_argb,
1957                    int src_stride_argb,
1958                    uint8_t* dst_argb1555,
1959                    int dst_stride_argb1555,
1960                    int width,
1961                    int height) {
1962   int y;
1963   void (*ARGBToARGB1555Row)(const uint8_t* src_argb, uint8_t* dst_rgb,
1964                             int width) = ARGBToARGB1555Row_C;
1965   if (!src_argb || !dst_argb1555 || width <= 0 || height == 0) {
1966     return -1;
1967   }
1968   if (height < 0) {
1969     height = -height;
1970     src_argb = src_argb + (height - 1) * src_stride_argb;
1971     src_stride_argb = -src_stride_argb;
1972   }
1973   // Coalesce rows.
1974   if (src_stride_argb == width * 4 && dst_stride_argb1555 == width * 2) {
1975     width *= height;
1976     height = 1;
1977     src_stride_argb = dst_stride_argb1555 = 0;
1978   }
1979 #if defined(HAS_ARGBTOARGB1555ROW_SSE2)
1980   if (TestCpuFlag(kCpuHasSSE2)) {
1981     ARGBToARGB1555Row = ARGBToARGB1555Row_Any_SSE2;
1982     if (IS_ALIGNED(width, 4)) {
1983       ARGBToARGB1555Row = ARGBToARGB1555Row_SSE2;
1984     }
1985   }
1986 #endif
1987 #if defined(HAS_ARGBTOARGB1555ROW_AVX2)
1988   if (TestCpuFlag(kCpuHasAVX2)) {
1989     ARGBToARGB1555Row = ARGBToARGB1555Row_Any_AVX2;
1990     if (IS_ALIGNED(width, 8)) {
1991       ARGBToARGB1555Row = ARGBToARGB1555Row_AVX2;
1992     }
1993   }
1994 #endif
1995 #if defined(HAS_ARGBTOARGB1555ROW_NEON)
1996   if (TestCpuFlag(kCpuHasNEON)) {
1997     ARGBToARGB1555Row = ARGBToARGB1555Row_Any_NEON;
1998     if (IS_ALIGNED(width, 8)) {
1999       ARGBToARGB1555Row = ARGBToARGB1555Row_NEON;
2000     }
2001   }
2002 #endif
2003 #if defined(HAS_ARGBTOARGB1555ROW_MSA)
2004   if (TestCpuFlag(kCpuHasMSA)) {
2005     ARGBToARGB1555Row = ARGBToARGB1555Row_Any_MSA;
2006     if (IS_ALIGNED(width, 8)) {
2007       ARGBToARGB1555Row = ARGBToARGB1555Row_MSA;
2008     }
2009   }
2010 #endif
2011 #if defined(HAS_ARGBTOARGB1555ROW_LSX)
2012   if (TestCpuFlag(kCpuHasLSX)) {
2013     ARGBToARGB1555Row = ARGBToARGB1555Row_Any_LSX;
2014     if (IS_ALIGNED(width, 8)) {
2015       ARGBToARGB1555Row = ARGBToARGB1555Row_LSX;
2016     }
2017   }
2018 #endif
2019 #if defined(HAS_ARGBTOARGB1555ROW_LASX)
2020   if (TestCpuFlag(kCpuHasLASX)) {
2021     ARGBToARGB1555Row = ARGBToARGB1555Row_Any_LASX;
2022     if (IS_ALIGNED(width, 16)) {
2023       ARGBToARGB1555Row = ARGBToARGB1555Row_LASX;
2024     }
2025   }
2026 #endif
2027 
2028   for (y = 0; y < height; ++y) {
2029     ARGBToARGB1555Row(src_argb, dst_argb1555, width);
2030     src_argb += src_stride_argb;
2031     dst_argb1555 += dst_stride_argb1555;
2032   }
2033   return 0;
2034 }
2035 
2036 // Convert ARGB To ARGB4444.
2037 LIBYUV_API
ARGBToARGB4444(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_argb4444,int dst_stride_argb4444,int width,int height)2038 int ARGBToARGB4444(const uint8_t* src_argb,
2039                    int src_stride_argb,
2040                    uint8_t* dst_argb4444,
2041                    int dst_stride_argb4444,
2042                    int width,
2043                    int height) {
2044   int y;
2045   void (*ARGBToARGB4444Row)(const uint8_t* src_argb, uint8_t* dst_rgb,
2046                             int width) = ARGBToARGB4444Row_C;
2047   if (!src_argb || !dst_argb4444 || width <= 0 || height == 0) {
2048     return -1;
2049   }
2050   if (height < 0) {
2051     height = -height;
2052     src_argb = src_argb + (height - 1) * src_stride_argb;
2053     src_stride_argb = -src_stride_argb;
2054   }
2055   // Coalesce rows.
2056   if (src_stride_argb == width * 4 && dst_stride_argb4444 == width * 2) {
2057     width *= height;
2058     height = 1;
2059     src_stride_argb = dst_stride_argb4444 = 0;
2060   }
2061 #if defined(HAS_ARGBTOARGB4444ROW_SSE2)
2062   if (TestCpuFlag(kCpuHasSSE2)) {
2063     ARGBToARGB4444Row = ARGBToARGB4444Row_Any_SSE2;
2064     if (IS_ALIGNED(width, 4)) {
2065       ARGBToARGB4444Row = ARGBToARGB4444Row_SSE2;
2066     }
2067   }
2068 #endif
2069 #if defined(HAS_ARGBTOARGB4444ROW_AVX2)
2070   if (TestCpuFlag(kCpuHasAVX2)) {
2071     ARGBToARGB4444Row = ARGBToARGB4444Row_Any_AVX2;
2072     if (IS_ALIGNED(width, 8)) {
2073       ARGBToARGB4444Row = ARGBToARGB4444Row_AVX2;
2074     }
2075   }
2076 #endif
2077 #if defined(HAS_ARGBTOARGB4444ROW_NEON)
2078   if (TestCpuFlag(kCpuHasNEON)) {
2079     ARGBToARGB4444Row = ARGBToARGB4444Row_Any_NEON;
2080     if (IS_ALIGNED(width, 8)) {
2081       ARGBToARGB4444Row = ARGBToARGB4444Row_NEON;
2082     }
2083   }
2084 #endif
2085 #if defined(HAS_ARGBTOARGB4444ROW_MSA)
2086   if (TestCpuFlag(kCpuHasMSA)) {
2087     ARGBToARGB4444Row = ARGBToARGB4444Row_Any_MSA;
2088     if (IS_ALIGNED(width, 8)) {
2089       ARGBToARGB4444Row = ARGBToARGB4444Row_MSA;
2090     }
2091   }
2092 #endif
2093 #if defined(HAS_ARGBTOARGB4444ROW_LSX)
2094   if (TestCpuFlag(kCpuHasLSX)) {
2095     ARGBToARGB4444Row = ARGBToARGB4444Row_Any_LSX;
2096     if (IS_ALIGNED(width, 8)) {
2097       ARGBToARGB4444Row = ARGBToARGB4444Row_LSX;
2098     }
2099   }
2100 #endif
2101 #if defined(HAS_ARGBTOARGB4444ROW_LASX)
2102   if (TestCpuFlag(kCpuHasLASX)) {
2103     ARGBToARGB4444Row = ARGBToARGB4444Row_Any_LASX;
2104     if (IS_ALIGNED(width, 16)) {
2105       ARGBToARGB4444Row = ARGBToARGB4444Row_LASX;
2106     }
2107   }
2108 #endif
2109 
2110   for (y = 0; y < height; ++y) {
2111     ARGBToARGB4444Row(src_argb, dst_argb4444, width);
2112     src_argb += src_stride_argb;
2113     dst_argb4444 += dst_stride_argb4444;
2114   }
2115   return 0;
2116 }
2117 
2118 // Convert ABGR To AR30.
2119 LIBYUV_API
ABGRToAR30(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_ar30,int dst_stride_ar30,int width,int height)2120 int ABGRToAR30(const uint8_t* src_abgr,
2121                int src_stride_abgr,
2122                uint8_t* dst_ar30,
2123                int dst_stride_ar30,
2124                int width,
2125                int height) {
2126   int y;
2127   void (*ABGRToAR30Row)(const uint8_t* src_abgr, uint8_t* dst_rgb, int width) =
2128       ABGRToAR30Row_C;
2129   if (!src_abgr || !dst_ar30 || width <= 0 || height == 0) {
2130     return -1;
2131   }
2132   if (height < 0) {
2133     height = -height;
2134     src_abgr = src_abgr + (height - 1) * src_stride_abgr;
2135     src_stride_abgr = -src_stride_abgr;
2136   }
2137   // Coalesce rows.
2138   if (src_stride_abgr == width * 4 && dst_stride_ar30 == width * 4) {
2139     width *= height;
2140     height = 1;
2141     src_stride_abgr = dst_stride_ar30 = 0;
2142   }
2143 #if defined(HAS_ABGRTOAR30ROW_SSSE3)
2144   if (TestCpuFlag(kCpuHasSSSE3)) {
2145     ABGRToAR30Row = ABGRToAR30Row_Any_SSSE3;
2146     if (IS_ALIGNED(width, 4)) {
2147       ABGRToAR30Row = ABGRToAR30Row_SSSE3;
2148     }
2149   }
2150 #endif
2151 #if defined(HAS_ABGRTOAR30ROW_AVX2)
2152   if (TestCpuFlag(kCpuHasAVX2)) {
2153     ABGRToAR30Row = ABGRToAR30Row_Any_AVX2;
2154     if (IS_ALIGNED(width, 8)) {
2155       ABGRToAR30Row = ABGRToAR30Row_AVX2;
2156     }
2157   }
2158 #endif
2159   for (y = 0; y < height; ++y) {
2160     ABGRToAR30Row(src_abgr, dst_ar30, width);
2161     src_abgr += src_stride_abgr;
2162     dst_ar30 += dst_stride_ar30;
2163   }
2164   return 0;
2165 }
2166 
2167 // Convert ARGB To AR30.
2168 LIBYUV_API
ARGBToAR30(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_ar30,int dst_stride_ar30,int width,int height)2169 int ARGBToAR30(const uint8_t* src_argb,
2170                int src_stride_argb,
2171                uint8_t* dst_ar30,
2172                int dst_stride_ar30,
2173                int width,
2174                int height) {
2175   int y;
2176   void (*ARGBToAR30Row)(const uint8_t* src_argb, uint8_t* dst_rgb, int width) =
2177       ARGBToAR30Row_C;
2178   if (!src_argb || !dst_ar30 || width <= 0 || height == 0) {
2179     return -1;
2180   }
2181   if (height < 0) {
2182     height = -height;
2183     src_argb = src_argb + (height - 1) * src_stride_argb;
2184     src_stride_argb = -src_stride_argb;
2185   }
2186   // Coalesce rows.
2187   if (src_stride_argb == width * 4 && dst_stride_ar30 == width * 4) {
2188     width *= height;
2189     height = 1;
2190     src_stride_argb = dst_stride_ar30 = 0;
2191   }
2192 #if defined(HAS_ARGBTOAR30ROW_SSSE3)
2193   if (TestCpuFlag(kCpuHasSSSE3)) {
2194     ARGBToAR30Row = ARGBToAR30Row_Any_SSSE3;
2195     if (IS_ALIGNED(width, 4)) {
2196       ARGBToAR30Row = ARGBToAR30Row_SSSE3;
2197     }
2198   }
2199 #endif
2200 #if defined(HAS_ARGBTOAR30ROW_AVX2)
2201   if (TestCpuFlag(kCpuHasAVX2)) {
2202     ARGBToAR30Row = ARGBToAR30Row_Any_AVX2;
2203     if (IS_ALIGNED(width, 8)) {
2204       ARGBToAR30Row = ARGBToAR30Row_AVX2;
2205     }
2206   }
2207 #endif
2208   for (y = 0; y < height; ++y) {
2209     ARGBToAR30Row(src_argb, dst_ar30, width);
2210     src_argb += src_stride_argb;
2211     dst_ar30 += dst_stride_ar30;
2212   }
2213   return 0;
2214 }
2215 
2216 // Convert ARGB to J420. (JPeg full range I420).
2217 LIBYUV_API
ARGBToJ420(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_yj,int dst_stride_yj,uint8_t * dst_uj,int dst_stride_uj,uint8_t * dst_vj,int dst_stride_vj,int width,int height)2218 int ARGBToJ420(const uint8_t* src_argb,
2219                int src_stride_argb,
2220                uint8_t* dst_yj,
2221                int dst_stride_yj,
2222                uint8_t* dst_uj,
2223                int dst_stride_uj,
2224                uint8_t* dst_vj,
2225                int dst_stride_vj,
2226                int width,
2227                int height) {
2228   int y;
2229   void (*ARGBToUVJRow)(const uint8_t* src_argb0, int src_stride_argb,
2230                        uint8_t* dst_uj, uint8_t* dst_vj, int width) =
2231       ARGBToUVJRow_C;
2232   void (*ARGBToYJRow)(const uint8_t* src_argb, uint8_t* dst_yj, int width) =
2233       ARGBToYJRow_C;
2234   if (!src_argb || !dst_yj || !dst_uj || !dst_vj || width <= 0 || height == 0) {
2235     return -1;
2236   }
2237   // Negative height means invert the image.
2238   if (height < 0) {
2239     height = -height;
2240     src_argb = src_argb + (height - 1) * src_stride_argb;
2241     src_stride_argb = -src_stride_argb;
2242   }
2243 #if defined(HAS_ARGBTOYJROW_NEON)
2244   if (TestCpuFlag(kCpuHasNEON)) {
2245     ARGBToYJRow = ARGBToYJRow_Any_NEON;
2246     if (IS_ALIGNED(width, 16)) {
2247       ARGBToYJRow = ARGBToYJRow_NEON;
2248     }
2249   }
2250 #endif
2251 #if defined(HAS_ARGBTOUVJROW_NEON)
2252   if (TestCpuFlag(kCpuHasNEON)) {
2253     ARGBToUVJRow = ARGBToUVJRow_Any_NEON;
2254     if (IS_ALIGNED(width, 16)) {
2255       ARGBToUVJRow = ARGBToUVJRow_NEON;
2256     }
2257   }
2258 #endif
2259 #if defined(HAS_ARGBTOYJROW_SSSE3)
2260   if (TestCpuFlag(kCpuHasSSSE3)) {
2261     ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
2262     if (IS_ALIGNED(width, 16)) {
2263       ARGBToYJRow = ARGBToYJRow_SSSE3;
2264     }
2265   }
2266 #endif
2267 #if defined(HAS_ARGBTOUVJROW_SSSE3)
2268   if (TestCpuFlag(kCpuHasSSSE3)) {
2269     ARGBToUVJRow = ARGBToUVJRow_Any_SSSE3;
2270     if (IS_ALIGNED(width, 16)) {
2271       ARGBToUVJRow = ARGBToUVJRow_SSSE3;
2272     }
2273   }
2274 #endif
2275 #if defined(HAS_ARGBTOYJROW_AVX2)
2276   if (TestCpuFlag(kCpuHasAVX2)) {
2277     ARGBToYJRow = ARGBToYJRow_Any_AVX2;
2278     if (IS_ALIGNED(width, 32)) {
2279       ARGBToYJRow = ARGBToYJRow_AVX2;
2280     }
2281   }
2282 #endif
2283 #if defined(HAS_ARGBTOUVJROW_AVX2)
2284   if (TestCpuFlag(kCpuHasAVX2)) {
2285     ARGBToUVJRow = ARGBToUVJRow_Any_AVX2;
2286     if (IS_ALIGNED(width, 32)) {
2287       ARGBToUVJRow = ARGBToUVJRow_AVX2;
2288     }
2289   }
2290 #endif
2291 #if defined(HAS_ARGBTOYJROW_MSA) && defined(HAS_ARGBTOUVJROW_MSA)
2292   if (TestCpuFlag(kCpuHasMSA)) {
2293     ARGBToYJRow = ARGBToYJRow_Any_MSA;
2294     ARGBToUVJRow = ARGBToUVJRow_Any_MSA;
2295     if (IS_ALIGNED(width, 16)) {
2296       ARGBToYJRow = ARGBToYJRow_MSA;
2297     }
2298     if (IS_ALIGNED(width, 32)) {
2299       ARGBToUVJRow = ARGBToUVJRow_MSA;
2300     }
2301   }
2302 #endif
2303 #if defined(HAS_ARGBTOYJROW_LSX) && defined(HAS_ARGBTOUVJROW_LSX)
2304   if (TestCpuFlag(kCpuHasLSX)) {
2305     ARGBToYJRow = ARGBToYJRow_Any_LSX;
2306     ARGBToUVJRow = ARGBToUVJRow_Any_LSX;
2307     if (IS_ALIGNED(width, 16)) {
2308       ARGBToYJRow = ARGBToYJRow_LSX;
2309       ARGBToUVJRow = ARGBToUVJRow_LSX;
2310     }
2311   }
2312 #endif
2313 #if defined(HAS_ARGBTOYJROW_LASX) && defined(HAS_ARGBTOUVJROW_LASX)
2314   if (TestCpuFlag(kCpuHasLASX)) {
2315     ARGBToYJRow = ARGBToYJRow_Any_LASX;
2316     ARGBToUVJRow = ARGBToUVJRow_Any_LASX;
2317     if (IS_ALIGNED(width, 32)) {
2318       ARGBToYJRow = ARGBToYJRow_LASX;
2319       ARGBToUVJRow = ARGBToUVJRow_LASX;
2320     }
2321   }
2322 #endif
2323 #if defined(HAS_ARGBTOYJROW_RVV)
2324   if (TestCpuFlag(kCpuHasRVV)) {
2325     ARGBToYJRow = ARGBToYJRow_RVV;
2326   }
2327 #endif
2328 
2329   for (y = 0; y < height - 1; y += 2) {
2330     ARGBToUVJRow(src_argb, src_stride_argb, dst_uj, dst_vj, width);
2331     ARGBToYJRow(src_argb, dst_yj, width);
2332     ARGBToYJRow(src_argb + src_stride_argb, dst_yj + dst_stride_yj, width);
2333     src_argb += src_stride_argb * 2;
2334     dst_yj += dst_stride_yj * 2;
2335     dst_uj += dst_stride_uj;
2336     dst_vj += dst_stride_vj;
2337   }
2338   if (height & 1) {
2339     ARGBToUVJRow(src_argb, 0, dst_uj, dst_vj, width);
2340     ARGBToYJRow(src_argb, dst_yj, width);
2341   }
2342   return 0;
2343 }
2344 
2345 // Convert ARGB to J422. (JPeg full range I422).
2346 LIBYUV_API
ARGBToJ422(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_yj,int dst_stride_yj,uint8_t * dst_uj,int dst_stride_uj,uint8_t * dst_vj,int dst_stride_vj,int width,int height)2347 int ARGBToJ422(const uint8_t* src_argb,
2348                int src_stride_argb,
2349                uint8_t* dst_yj,
2350                int dst_stride_yj,
2351                uint8_t* dst_uj,
2352                int dst_stride_uj,
2353                uint8_t* dst_vj,
2354                int dst_stride_vj,
2355                int width,
2356                int height) {
2357   int y;
2358   void (*ARGBToUVJRow)(const uint8_t* src_argb0, int src_stride_argb,
2359                        uint8_t* dst_uj, uint8_t* dst_vj, int width) =
2360       ARGBToUVJRow_C;
2361   void (*ARGBToYJRow)(const uint8_t* src_argb, uint8_t* dst_yj, int width) =
2362       ARGBToYJRow_C;
2363   if (!src_argb || !dst_yj || !dst_uj || !dst_vj || width <= 0 || height == 0) {
2364     return -1;
2365   }
2366   // Negative height means invert the image.
2367   if (height < 0) {
2368     height = -height;
2369     src_argb = src_argb + (height - 1) * src_stride_argb;
2370     src_stride_argb = -src_stride_argb;
2371   }
2372   // Coalesce rows.
2373   if (src_stride_argb == width * 4 && dst_stride_yj == width &&
2374       dst_stride_uj * 2 == width && dst_stride_vj * 2 == width) {
2375     width *= height;
2376     height = 1;
2377     src_stride_argb = dst_stride_yj = dst_stride_uj = dst_stride_vj = 0;
2378   }
2379 #if defined(HAS_ARGBTOYJROW_SSSE3)
2380   if (TestCpuFlag(kCpuHasSSSE3)) {
2381     ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
2382     if (IS_ALIGNED(width, 16)) {
2383       ARGBToYJRow = ARGBToYJRow_SSSE3;
2384     }
2385   }
2386 #endif
2387 #if defined(HAS_ARGBTOUVJROW_SSSE3)
2388   if (TestCpuFlag(kCpuHasSSSE3)) {
2389     ARGBToUVJRow = ARGBToUVJRow_Any_SSSE3;
2390     if (IS_ALIGNED(width, 16)) {
2391       ARGBToUVJRow = ARGBToUVJRow_SSSE3;
2392     }
2393   }
2394 #endif
2395 #if defined(HAS_ARGBTOYJROW_AVX2)
2396   if (TestCpuFlag(kCpuHasAVX2)) {
2397     ARGBToYJRow = ARGBToYJRow_Any_AVX2;
2398     if (IS_ALIGNED(width, 32)) {
2399       ARGBToYJRow = ARGBToYJRow_AVX2;
2400     }
2401   }
2402 #endif
2403 #if defined(HAS_ARGBTOUVJROW_AVX2)
2404   if (TestCpuFlag(kCpuHasAVX2)) {
2405     ARGBToUVJRow = ARGBToUVJRow_Any_AVX2;
2406     if (IS_ALIGNED(width, 32)) {
2407       ARGBToUVJRow = ARGBToUVJRow_AVX2;
2408     }
2409   }
2410 #endif
2411 #if defined(HAS_ARGBTOYJROW_NEON)
2412   if (TestCpuFlag(kCpuHasNEON)) {
2413     ARGBToYJRow = ARGBToYJRow_Any_NEON;
2414     if (IS_ALIGNED(width, 16)) {
2415       ARGBToYJRow = ARGBToYJRow_NEON;
2416     }
2417   }
2418 #endif
2419 #if defined(HAS_ARGBTOUVJROW_NEON)
2420   if (TestCpuFlag(kCpuHasNEON)) {
2421     ARGBToUVJRow = ARGBToUVJRow_Any_NEON;
2422     if (IS_ALIGNED(width, 16)) {
2423       ARGBToUVJRow = ARGBToUVJRow_NEON;
2424     }
2425   }
2426 #endif
2427 #if defined(HAS_ARGBTOYJROW_MSA) && defined(HAS_ARGBTOUVJROW_MSA)
2428   if (TestCpuFlag(kCpuHasMSA)) {
2429     ARGBToYJRow = ARGBToYJRow_Any_MSA;
2430     ARGBToUVJRow = ARGBToUVJRow_Any_MSA;
2431     if (IS_ALIGNED(width, 16)) {
2432       ARGBToYJRow = ARGBToYJRow_MSA;
2433     }
2434     if (IS_ALIGNED(width, 32)) {
2435       ARGBToUVJRow = ARGBToUVJRow_MSA;
2436     }
2437   }
2438 #endif
2439 #if defined(HAS_ARGBTOYJROW_LSX) && defined(HAS_ARGBTOUVJROW_LSX)
2440   if (TestCpuFlag(kCpuHasLSX)) {
2441     ARGBToYJRow = ARGBToYJRow_Any_LSX;
2442     ARGBToUVJRow = ARGBToUVJRow_Any_LSX;
2443     if (IS_ALIGNED(width, 16)) {
2444       ARGBToYJRow = ARGBToYJRow_LSX;
2445       ARGBToUVJRow = ARGBToUVJRow_LSX;
2446     }
2447   }
2448 #endif
2449 #if defined(HAS_ARGBTOYJROW_LASX) && defined(HAS_ARGBTOUVJROW_LASX)
2450   if (TestCpuFlag(kCpuHasLASX)) {
2451     ARGBToYJRow = ARGBToYJRow_Any_LASX;
2452     ARGBToUVJRow = ARGBToUVJRow_Any_LASX;
2453     if (IS_ALIGNED(width, 32)) {
2454       ARGBToYJRow = ARGBToYJRow_LASX;
2455       ARGBToUVJRow = ARGBToUVJRow_LASX;
2456     }
2457   }
2458 #endif
2459 #if defined(HAS_ARGBTOYJROW_RVV)
2460   if (TestCpuFlag(kCpuHasRVV)) {
2461     ARGBToYJRow = ARGBToYJRow_RVV;
2462   }
2463 #endif
2464 
2465   for (y = 0; y < height; ++y) {
2466     ARGBToUVJRow(src_argb, 0, dst_uj, dst_vj, width);
2467     ARGBToYJRow(src_argb, dst_yj, width);
2468     src_argb += src_stride_argb;
2469     dst_yj += dst_stride_yj;
2470     dst_uj += dst_stride_uj;
2471     dst_vj += dst_stride_vj;
2472   }
2473   return 0;
2474 }
2475 
2476 // Convert ARGB to J400.
2477 LIBYUV_API
ARGBToJ400(const uint8_t * src_argb,int src_stride_argb,uint8_t * dst_yj,int dst_stride_yj,int width,int height)2478 int ARGBToJ400(const uint8_t* src_argb,
2479                int src_stride_argb,
2480                uint8_t* dst_yj,
2481                int dst_stride_yj,
2482                int width,
2483                int height) {
2484   int y;
2485   void (*ARGBToYJRow)(const uint8_t* src_argb, uint8_t* dst_yj, int width) =
2486       ARGBToYJRow_C;
2487   if (!src_argb || !dst_yj || width <= 0 || height == 0) {
2488     return -1;
2489   }
2490   if (height < 0) {
2491     height = -height;
2492     src_argb = src_argb + (height - 1) * src_stride_argb;
2493     src_stride_argb = -src_stride_argb;
2494   }
2495   // Coalesce rows.
2496   if (src_stride_argb == width * 4 && dst_stride_yj == width) {
2497     width *= height;
2498     height = 1;
2499     src_stride_argb = dst_stride_yj = 0;
2500   }
2501 #if defined(HAS_ARGBTOYJROW_SSSE3)
2502   if (TestCpuFlag(kCpuHasSSSE3)) {
2503     ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
2504     if (IS_ALIGNED(width, 16)) {
2505       ARGBToYJRow = ARGBToYJRow_SSSE3;
2506     }
2507   }
2508 #endif
2509 #if defined(HAS_ARGBTOYJROW_AVX2)
2510   if (TestCpuFlag(kCpuHasAVX2)) {
2511     ARGBToYJRow = ARGBToYJRow_Any_AVX2;
2512     if (IS_ALIGNED(width, 32)) {
2513       ARGBToYJRow = ARGBToYJRow_AVX2;
2514     }
2515   }
2516 #endif
2517 #if defined(HAS_ARGBTOYJROW_NEON)
2518   if (TestCpuFlag(kCpuHasNEON)) {
2519     ARGBToYJRow = ARGBToYJRow_Any_NEON;
2520     if (IS_ALIGNED(width, 16)) {
2521       ARGBToYJRow = ARGBToYJRow_NEON;
2522     }
2523   }
2524 #endif
2525 #if defined(HAS_ARGBTOYJROW_MSA)
2526   if (TestCpuFlag(kCpuHasMSA)) {
2527     ARGBToYJRow = ARGBToYJRow_Any_MSA;
2528     if (IS_ALIGNED(width, 16)) {
2529       ARGBToYJRow = ARGBToYJRow_MSA;
2530     }
2531   }
2532 #endif
2533 #if defined(HAS_ARGBTOYJROW_RVV)
2534   if (TestCpuFlag(kCpuHasRVV)) {
2535     ARGBToYJRow = ARGBToYJRow_RVV;
2536   }
2537 #endif
2538 
2539   for (y = 0; y < height; ++y) {
2540     ARGBToYJRow(src_argb, dst_yj, width);
2541     src_argb += src_stride_argb;
2542     dst_yj += dst_stride_yj;
2543   }
2544   return 0;
2545 }
2546 
2547 // Convert RGBA to J400.
2548 LIBYUV_API
RGBAToJ400(const uint8_t * src_rgba,int src_stride_rgba,uint8_t * dst_yj,int dst_stride_yj,int width,int height)2549 int RGBAToJ400(const uint8_t* src_rgba,
2550                int src_stride_rgba,
2551                uint8_t* dst_yj,
2552                int dst_stride_yj,
2553                int width,
2554                int height) {
2555   int y;
2556   void (*RGBAToYJRow)(const uint8_t* src_rgba, uint8_t* dst_yj, int width) =
2557       RGBAToYJRow_C;
2558   if (!src_rgba || !dst_yj || width <= 0 || height == 0) {
2559     return -1;
2560   }
2561   if (height < 0) {
2562     height = -height;
2563     src_rgba = src_rgba + (height - 1) * src_stride_rgba;
2564     src_stride_rgba = -src_stride_rgba;
2565   }
2566   // Coalesce rows.
2567   if (src_stride_rgba == width * 4 && dst_stride_yj == width) {
2568     width *= height;
2569     height = 1;
2570     src_stride_rgba = dst_stride_yj = 0;
2571   }
2572 #if defined(HAS_RGBATOYJROW_SSSE3)
2573   if (TestCpuFlag(kCpuHasSSSE3)) {
2574     RGBAToYJRow = RGBAToYJRow_Any_SSSE3;
2575     if (IS_ALIGNED(width, 16)) {
2576       RGBAToYJRow = RGBAToYJRow_SSSE3;
2577     }
2578   }
2579 #endif
2580 #if defined(HAS_RGBATOYJROW_AVX2)
2581   if (TestCpuFlag(kCpuHasAVX2)) {
2582     RGBAToYJRow = RGBAToYJRow_Any_AVX2;
2583     if (IS_ALIGNED(width, 32)) {
2584       RGBAToYJRow = RGBAToYJRow_AVX2;
2585     }
2586   }
2587 #endif
2588 #if defined(HAS_RGBATOYJROW_NEON)
2589   if (TestCpuFlag(kCpuHasNEON)) {
2590     RGBAToYJRow = RGBAToYJRow_Any_NEON;
2591     if (IS_ALIGNED(width, 16)) {
2592       RGBAToYJRow = RGBAToYJRow_NEON;
2593     }
2594   }
2595 #endif
2596 #if defined(HAS_RGBATOYJROW_MSA)
2597   if (TestCpuFlag(kCpuHasMSA)) {
2598     RGBAToYJRow = RGBAToYJRow_Any_MSA;
2599     if (IS_ALIGNED(width, 16)) {
2600       RGBAToYJRow = RGBAToYJRow_MSA;
2601     }
2602   }
2603 #endif
2604 #if defined(HAS_RGBATOYJROW_LSX)
2605   if (TestCpuFlag(kCpuHasLSX)) {
2606     RGBAToYJRow = RGBAToYJRow_Any_LSX;
2607     if (IS_ALIGNED(width, 16)) {
2608       RGBAToYJRow = RGBAToYJRow_LSX;
2609     }
2610   }
2611 #endif
2612 #if defined(HAS_RGBATOYJROW_LASX)
2613   if (TestCpuFlag(kCpuHasLASX)) {
2614     RGBAToYJRow = RGBAToYJRow_Any_LASX;
2615     if (IS_ALIGNED(width, 32)) {
2616       RGBAToYJRow = RGBAToYJRow_LASX;
2617     }
2618   }
2619 #endif
2620 #if defined(HAS_RGBATOYJROW_RVV)
2621   if (TestCpuFlag(kCpuHasRVV)) {
2622     RGBAToYJRow = RGBAToYJRow_RVV;
2623   }
2624 #endif
2625 
2626   for (y = 0; y < height; ++y) {
2627     RGBAToYJRow(src_rgba, dst_yj, width);
2628     src_rgba += src_stride_rgba;
2629     dst_yj += dst_stride_yj;
2630   }
2631   return 0;
2632 }
2633 
2634 // Convert ABGR to J420. (JPeg full range I420).
2635 LIBYUV_API
ABGRToJ420(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_yj,int dst_stride_yj,uint8_t * dst_uj,int dst_stride_uj,uint8_t * dst_vj,int dst_stride_vj,int width,int height)2636 int ABGRToJ420(const uint8_t* src_abgr,
2637                int src_stride_abgr,
2638                uint8_t* dst_yj,
2639                int dst_stride_yj,
2640                uint8_t* dst_uj,
2641                int dst_stride_uj,
2642                uint8_t* dst_vj,
2643                int dst_stride_vj,
2644                int width,
2645                int height) {
2646   int y;
2647   void (*ABGRToUVJRow)(const uint8_t* src_abgr0, int src_stride_abgr,
2648                        uint8_t* dst_uj, uint8_t* dst_vj, int width) =
2649       ABGRToUVJRow_C;
2650   void (*ABGRToYJRow)(const uint8_t* src_abgr, uint8_t* dst_yj, int width) =
2651       ABGRToYJRow_C;
2652   if (!src_abgr || !dst_yj || !dst_uj || !dst_vj || width <= 0 || height == 0) {
2653     return -1;
2654   }
2655   // Negative height means invert the image.
2656   if (height < 0) {
2657     height = -height;
2658     src_abgr = src_abgr + (height - 1) * src_stride_abgr;
2659     src_stride_abgr = -src_stride_abgr;
2660   }
2661 #if defined(HAS_ABGRTOYJROW_SSSE3)
2662   if (TestCpuFlag(kCpuHasSSSE3)) {
2663     ABGRToYJRow = ABGRToYJRow_Any_SSSE3;
2664     if (IS_ALIGNED(width, 16)) {
2665       ABGRToYJRow = ABGRToYJRow_SSSE3;
2666     }
2667   }
2668 #endif
2669 #if defined(HAS_ABGRTOUVJROW_SSSE3)
2670   if (TestCpuFlag(kCpuHasSSSE3)) {
2671     ABGRToUVJRow = ABGRToUVJRow_Any_SSSE3;
2672     if (IS_ALIGNED(width, 16)) {
2673       ABGRToUVJRow = ABGRToUVJRow_SSSE3;
2674     }
2675   }
2676 #endif
2677 #if defined(HAS_ABGRTOYJROW_AVX2)
2678   if (TestCpuFlag(kCpuHasAVX2)) {
2679     ABGRToYJRow = ABGRToYJRow_Any_AVX2;
2680     if (IS_ALIGNED(width, 32)) {
2681       ABGRToYJRow = ABGRToYJRow_AVX2;
2682     }
2683   }
2684 #endif
2685 #if defined(HAS_ABGRTOUVJROW_AVX2)
2686   if (TestCpuFlag(kCpuHasAVX2)) {
2687     ABGRToUVJRow = ABGRToUVJRow_Any_AVX2;
2688     if (IS_ALIGNED(width, 32)) {
2689       ABGRToUVJRow = ABGRToUVJRow_AVX2;
2690     }
2691   }
2692 #endif
2693 #if defined(HAS_ABGRTOYJROW_NEON)
2694   if (TestCpuFlag(kCpuHasNEON)) {
2695     ABGRToYJRow = ABGRToYJRow_Any_NEON;
2696     if (IS_ALIGNED(width, 16)) {
2697       ABGRToYJRow = ABGRToYJRow_NEON;
2698     }
2699   }
2700 #endif
2701 #if defined(HAS_ABGRTOUVJROW_NEON)
2702   if (TestCpuFlag(kCpuHasNEON)) {
2703     ABGRToUVJRow = ABGRToUVJRow_Any_NEON;
2704     if (IS_ALIGNED(width, 16)) {
2705       ABGRToUVJRow = ABGRToUVJRow_NEON;
2706     }
2707   }
2708 #endif
2709 #if defined(HAS_ABGRTOYJROW_MSA) && defined(HAS_ABGRTOUVJROW_MSA)
2710   if (TestCpuFlag(kCpuHasMSA)) {
2711     ABGRToYJRow = ABGRToYJRow_Any_MSA;
2712     ABGRToUVJRow = ABGRToUVJRow_Any_MSA;
2713     if (IS_ALIGNED(width, 16)) {
2714       ABGRToYJRow = ABGRToYJRow_MSA;
2715       ABGRToUVJRow = ABGRToUVJRow_MSA;
2716     }
2717   }
2718 #endif
2719 #if defined(HAS_ABGRTOYJROW_LSX)
2720   if (TestCpuFlag(kCpuHasLSX)) {
2721     ABGRToYJRow = ABGRToYJRow_Any_LSX;
2722     if (IS_ALIGNED(width, 16)) {
2723       ABGRToYJRow = ABGRToYJRow_LSX;
2724     }
2725   }
2726 #endif
2727 #if defined(HAS_ABGRTOYJROW_LASX)
2728   if (TestCpuFlag(kCpuHasLASX)) {
2729     ABGRToYJRow = ABGRToYJRow_Any_LASX;
2730     if (IS_ALIGNED(width, 32)) {
2731       ABGRToYJRow = ABGRToYJRow_LASX;
2732     }
2733   }
2734 #endif
2735 #if defined(HAS_ABGRTOYJROW_RVV)
2736   if (TestCpuFlag(kCpuHasRVV)) {
2737     ABGRToYJRow = ABGRToYJRow_RVV;
2738   }
2739 #endif
2740 
2741   for (y = 0; y < height - 1; y += 2) {
2742     ABGRToUVJRow(src_abgr, src_stride_abgr, dst_uj, dst_vj, width);
2743     ABGRToYJRow(src_abgr, dst_yj, width);
2744     ABGRToYJRow(src_abgr + src_stride_abgr, dst_yj + dst_stride_yj, width);
2745     src_abgr += src_stride_abgr * 2;
2746     dst_yj += dst_stride_yj * 2;
2747     dst_uj += dst_stride_uj;
2748     dst_vj += dst_stride_vj;
2749   }
2750   if (height & 1) {
2751     ABGRToUVJRow(src_abgr, 0, dst_uj, dst_vj, width);
2752     ABGRToYJRow(src_abgr, dst_yj, width);
2753   }
2754   return 0;
2755 }
2756 
2757 // Convert ABGR to J422. (JPeg full range I422).
2758 LIBYUV_API
ABGRToJ422(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_yj,int dst_stride_yj,uint8_t * dst_uj,int dst_stride_uj,uint8_t * dst_vj,int dst_stride_vj,int width,int height)2759 int ABGRToJ422(const uint8_t* src_abgr,
2760                int src_stride_abgr,
2761                uint8_t* dst_yj,
2762                int dst_stride_yj,
2763                uint8_t* dst_uj,
2764                int dst_stride_uj,
2765                uint8_t* dst_vj,
2766                int dst_stride_vj,
2767                int width,
2768                int height) {
2769   int y;
2770   void (*ABGRToUVJRow)(const uint8_t* src_abgr0, int src_stride_abgr,
2771                        uint8_t* dst_uj, uint8_t* dst_vj, int width) =
2772       ABGRToUVJRow_C;
2773   void (*ABGRToYJRow)(const uint8_t* src_abgr, uint8_t* dst_yj, int width) =
2774       ABGRToYJRow_C;
2775   if (!src_abgr || !dst_yj || !dst_uj || !dst_vj || width <= 0 || height == 0) {
2776     return -1;
2777   }
2778   // Negative height means invert the image.
2779   if (height < 0) {
2780     height = -height;
2781     src_abgr = src_abgr + (height - 1) * src_stride_abgr;
2782     src_stride_abgr = -src_stride_abgr;
2783   }
2784   // Coalesce rows.
2785   if (src_stride_abgr == width * 4 && dst_stride_yj == width &&
2786       dst_stride_uj * 2 == width && dst_stride_vj * 2 == width) {
2787     width *= height;
2788     height = 1;
2789     src_stride_abgr = dst_stride_yj = dst_stride_uj = dst_stride_vj = 0;
2790   }
2791 #if defined(HAS_ABGRTOYJROW_SSSE3)
2792   if (TestCpuFlag(kCpuHasSSSE3)) {
2793     ABGRToYJRow = ABGRToYJRow_Any_SSSE3;
2794     if (IS_ALIGNED(width, 16)) {
2795       ABGRToYJRow = ABGRToYJRow_SSSE3;
2796     }
2797   }
2798 #endif
2799 #if defined(HAS_ABGRTOUVJROW_SSSE3)
2800   if (TestCpuFlag(kCpuHasSSSE3)) {
2801     ABGRToUVJRow = ABGRToUVJRow_Any_SSSE3;
2802     if (IS_ALIGNED(width, 16)) {
2803       ABGRToUVJRow = ABGRToUVJRow_SSSE3;
2804     }
2805   }
2806 #endif
2807 #if defined(HAS_ABGRTOYJROW_AVX2)
2808   if (TestCpuFlag(kCpuHasAVX2)) {
2809     ABGRToYJRow = ABGRToYJRow_Any_AVX2;
2810     if (IS_ALIGNED(width, 32)) {
2811       ABGRToYJRow = ABGRToYJRow_AVX2;
2812     }
2813   }
2814 #endif
2815 #if defined(HAS_ABGRTOUVJROW_AVX2)
2816   if (TestCpuFlag(kCpuHasAVX2)) {
2817     ABGRToUVJRow = ABGRToUVJRow_Any_AVX2;
2818     if (IS_ALIGNED(width, 32)) {
2819       ABGRToUVJRow = ABGRToUVJRow_AVX2;
2820     }
2821   }
2822 #endif
2823 #if defined(HAS_ABGRTOYJROW_NEON)
2824   if (TestCpuFlag(kCpuHasNEON)) {
2825     ABGRToYJRow = ABGRToYJRow_Any_NEON;
2826     if (IS_ALIGNED(width, 16)) {
2827       ABGRToYJRow = ABGRToYJRow_NEON;
2828     }
2829   }
2830 #endif
2831 #if defined(HAS_ABGRTOUVJROW_NEON)
2832   if (TestCpuFlag(kCpuHasNEON)) {
2833     ABGRToUVJRow = ABGRToUVJRow_Any_NEON;
2834     if (IS_ALIGNED(width, 16)) {
2835       ABGRToUVJRow = ABGRToUVJRow_NEON;
2836     }
2837   }
2838 #endif
2839 #if defined(HAS_ABGRTOYJROW_MSA) && defined(HAS_ABGRTOUVJROW_MSA)
2840   if (TestCpuFlag(kCpuHasMSA)) {
2841     ABGRToYJRow = ABGRToYJRow_Any_MSA;
2842     ABGRToUVJRow = ABGRToUVJRow_Any_MSA;
2843     if (IS_ALIGNED(width, 16)) {
2844       ABGRToYJRow = ABGRToYJRow_MSA;
2845     }
2846     if (IS_ALIGNED(width, 32)) {
2847       ABGRToUVJRow = ABGRToUVJRow_MSA;
2848     }
2849   }
2850 #endif
2851 #if defined(HAS_ABGRTOYJROW_LSX)
2852   if (TestCpuFlag(kCpuHasLSX)) {
2853     ABGRToYJRow = ABGRToYJRow_Any_LSX;
2854     if (IS_ALIGNED(width, 16)) {
2855       ABGRToYJRow = ABGRToYJRow_LSX;
2856     }
2857   }
2858 #endif
2859 #if defined(HAS_ABGRTOYJROW_LASX)
2860   if (TestCpuFlag(kCpuHasLASX)) {
2861     ABGRToYJRow = ABGRToYJRow_Any_LASX;
2862     if (IS_ALIGNED(width, 32)) {
2863       ABGRToYJRow = ABGRToYJRow_LASX;
2864     }
2865   }
2866 #endif
2867 #if defined(HAS_ABGRTOYJROW_RVV)
2868   if (TestCpuFlag(kCpuHasRVV)) {
2869     ABGRToYJRow = ABGRToYJRow_RVV;
2870   }
2871 #endif
2872 
2873   for (y = 0; y < height; ++y) {
2874     ABGRToUVJRow(src_abgr, 0, dst_uj, dst_vj, width);
2875     ABGRToYJRow(src_abgr, dst_yj, width);
2876     src_abgr += src_stride_abgr;
2877     dst_yj += dst_stride_yj;
2878     dst_uj += dst_stride_uj;
2879     dst_vj += dst_stride_vj;
2880   }
2881   return 0;
2882 }
2883 
2884 // Convert ABGR to J400.
2885 LIBYUV_API
ABGRToJ400(const uint8_t * src_abgr,int src_stride_abgr,uint8_t * dst_yj,int dst_stride_yj,int width,int height)2886 int ABGRToJ400(const uint8_t* src_abgr,
2887                int src_stride_abgr,
2888                uint8_t* dst_yj,
2889                int dst_stride_yj,
2890                int width,
2891                int height) {
2892   int y;
2893   void (*ABGRToYJRow)(const uint8_t* src_abgr, uint8_t* dst_yj, int width) =
2894       ABGRToYJRow_C;
2895   if (!src_abgr || !dst_yj || width <= 0 || height == 0) {
2896     return -1;
2897   }
2898   if (height < 0) {
2899     height = -height;
2900     src_abgr = src_abgr + (height - 1) * src_stride_abgr;
2901     src_stride_abgr = -src_stride_abgr;
2902   }
2903   // Coalesce rows.
2904   if (src_stride_abgr == width * 4 && dst_stride_yj == width) {
2905     width *= height;
2906     height = 1;
2907     src_stride_abgr = dst_stride_yj = 0;
2908   }
2909 #if defined(HAS_ABGRTOYJROW_SSSE3)
2910   if (TestCpuFlag(kCpuHasSSSE3)) {
2911     ABGRToYJRow = ABGRToYJRow_Any_SSSE3;
2912     if (IS_ALIGNED(width, 16)) {
2913       ABGRToYJRow = ABGRToYJRow_SSSE3;
2914     }
2915   }
2916 #endif
2917 #if defined(HAS_ABGRTOYJROW_AVX2)
2918   if (TestCpuFlag(kCpuHasAVX2)) {
2919     ABGRToYJRow = ABGRToYJRow_Any_AVX2;
2920     if (IS_ALIGNED(width, 32)) {
2921       ABGRToYJRow = ABGRToYJRow_AVX2;
2922     }
2923   }
2924 #endif
2925 #if defined(HAS_ABGRTOYJROW_NEON)
2926   if (TestCpuFlag(kCpuHasNEON)) {
2927     ABGRToYJRow = ABGRToYJRow_Any_NEON;
2928     if (IS_ALIGNED(width, 16)) {
2929       ABGRToYJRow = ABGRToYJRow_NEON;
2930     }
2931   }
2932 #endif
2933 #if defined(HAS_ABGRTOYJROW_MSA)
2934   if (TestCpuFlag(kCpuHasMSA)) {
2935     ABGRToYJRow = ABGRToYJRow_Any_MSA;
2936     if (IS_ALIGNED(width, 16)) {
2937       ABGRToYJRow = ABGRToYJRow_MSA;
2938     }
2939   }
2940 #endif
2941 #if defined(HAS_ABGRTOYJROW_LSX)
2942   if (TestCpuFlag(kCpuHasLSX)) {
2943     ABGRToYJRow = ABGRToYJRow_Any_LSX;
2944     if (IS_ALIGNED(width, 16)) {
2945       ABGRToYJRow = ABGRToYJRow_LSX;
2946     }
2947   }
2948 #endif
2949 #if defined(HAS_ABGRTOYJROW_LASX)
2950   if (TestCpuFlag(kCpuHasLASX)) {
2951     ABGRToYJRow = ABGRToYJRow_Any_LASX;
2952     if (IS_ALIGNED(width, 32)) {
2953       ABGRToYJRow = ABGRToYJRow_LASX;
2954     }
2955   }
2956 #endif
2957 #if defined(HAS_ABGRTOYJROW_RVV)
2958   if (TestCpuFlag(kCpuHasRVV)) {
2959     ABGRToYJRow = ABGRToYJRow_RVV;
2960   }
2961 #endif
2962 
2963   for (y = 0; y < height; ++y) {
2964     ABGRToYJRow(src_abgr, dst_yj, width);
2965     src_abgr += src_stride_abgr;
2966     dst_yj += dst_stride_yj;
2967   }
2968   return 0;
2969 }
2970 
2971 // Convert ARGB to AR64.
2972 LIBYUV_API
ARGBToAR64(const uint8_t * src_argb,int src_stride_argb,uint16_t * dst_ar64,int dst_stride_ar64,int width,int height)2973 int ARGBToAR64(const uint8_t* src_argb,
2974                int src_stride_argb,
2975                uint16_t* dst_ar64,
2976                int dst_stride_ar64,
2977                int width,
2978                int height) {
2979   int y;
2980   void (*ARGBToAR64Row)(const uint8_t* src_argb, uint16_t* dst_ar64,
2981                         int width) = ARGBToAR64Row_C;
2982   if (!src_argb || !dst_ar64 || width <= 0 || height == 0) {
2983     return -1;
2984   }
2985   // Negative height means invert the image.
2986   if (height < 0) {
2987     height = -height;
2988     src_argb = src_argb + (height - 1) * src_stride_argb;
2989     src_stride_argb = -src_stride_argb;
2990   }
2991   // Coalesce rows.
2992   if (src_stride_argb == width * 4 && dst_stride_ar64 == width * 4) {
2993     width *= height;
2994     height = 1;
2995     src_stride_argb = dst_stride_ar64 = 0;
2996   }
2997 #if defined(HAS_ARGBTOAR64ROW_SSSE3)
2998   if (TestCpuFlag(kCpuHasSSSE3)) {
2999     ARGBToAR64Row = ARGBToAR64Row_Any_SSSE3;
3000     if (IS_ALIGNED(width, 4)) {
3001       ARGBToAR64Row = ARGBToAR64Row_SSSE3;
3002     }
3003   }
3004 #endif
3005 #if defined(HAS_ARGBTOAR64ROW_AVX2)
3006   if (TestCpuFlag(kCpuHasAVX2)) {
3007     ARGBToAR64Row = ARGBToAR64Row_Any_AVX2;
3008     if (IS_ALIGNED(width, 8)) {
3009       ARGBToAR64Row = ARGBToAR64Row_AVX2;
3010     }
3011   }
3012 #endif
3013 #if defined(HAS_ARGBTOAR64ROW_NEON)
3014   if (TestCpuFlag(kCpuHasNEON)) {
3015     ARGBToAR64Row = ARGBToAR64Row_Any_NEON;
3016     if (IS_ALIGNED(width, 8)) {
3017       ARGBToAR64Row = ARGBToAR64Row_NEON;
3018     }
3019   }
3020 #endif
3021 #if defined(HAS_ARGBTOAR64ROW_RVV)
3022   if (TestCpuFlag(kCpuHasRVV)) {
3023     ARGBToAR64Row = ARGBToAR64Row_RVV;
3024   }
3025 #endif
3026 
3027   for (y = 0; y < height; ++y) {
3028     ARGBToAR64Row(src_argb, dst_ar64, width);
3029     src_argb += src_stride_argb;
3030     dst_ar64 += dst_stride_ar64;
3031   }
3032   return 0;
3033 }
3034 
3035 // Convert ARGB to AB64.
3036 LIBYUV_API
ARGBToAB64(const uint8_t * src_argb,int src_stride_argb,uint16_t * dst_ab64,int dst_stride_ab64,int width,int height)3037 int ARGBToAB64(const uint8_t* src_argb,
3038                int src_stride_argb,
3039                uint16_t* dst_ab64,
3040                int dst_stride_ab64,
3041                int width,
3042                int height) {
3043   int y;
3044   void (*ARGBToAB64Row)(const uint8_t* src_argb, uint16_t* dst_ar64,
3045                         int width) = ARGBToAB64Row_C;
3046   if (!src_argb || !dst_ab64 || width <= 0 || height == 0) {
3047     return -1;
3048   }
3049   // Negative height means invert the image.
3050   if (height < 0) {
3051     height = -height;
3052     src_argb = src_argb + (height - 1) * src_stride_argb;
3053     src_stride_argb = -src_stride_argb;
3054   }
3055   // Coalesce rows.
3056   if (src_stride_argb == width * 4 && dst_stride_ab64 == width * 4) {
3057     width *= height;
3058     height = 1;
3059     src_stride_argb = dst_stride_ab64 = 0;
3060   }
3061 #if defined(HAS_ARGBTOAB64ROW_SSSE3)
3062   if (TestCpuFlag(kCpuHasSSSE3)) {
3063     ARGBToAB64Row = ARGBToAB64Row_Any_SSSE3;
3064     if (IS_ALIGNED(width, 4)) {
3065       ARGBToAB64Row = ARGBToAB64Row_SSSE3;
3066     }
3067   }
3068 #endif
3069 #if defined(HAS_ARGBTOAB64ROW_AVX2)
3070   if (TestCpuFlag(kCpuHasAVX2)) {
3071     ARGBToAB64Row = ARGBToAB64Row_Any_AVX2;
3072     if (IS_ALIGNED(width, 8)) {
3073       ARGBToAB64Row = ARGBToAB64Row_AVX2;
3074     }
3075   }
3076 #endif
3077 #if defined(HAS_ARGBTOAB64ROW_NEON)
3078   if (TestCpuFlag(kCpuHasNEON)) {
3079     ARGBToAB64Row = ARGBToAB64Row_Any_NEON;
3080     if (IS_ALIGNED(width, 8)) {
3081       ARGBToAB64Row = ARGBToAB64Row_NEON;
3082     }
3083   }
3084 #endif
3085 #if defined(HAS_ARGBTOAB64ROW_RVV)
3086   if (TestCpuFlag(kCpuHasRVV)) {
3087     ARGBToAB64Row = ARGBToAB64Row_RVV;
3088   }
3089 #endif
3090 
3091   for (y = 0; y < height; ++y) {
3092     ARGBToAB64Row(src_argb, dst_ab64, width);
3093     src_argb += src_stride_argb;
3094     dst_ab64 += dst_stride_ab64;
3095   }
3096   return 0;
3097 }
3098 
3099 // Enabled if 1 pass is available
3100 #if defined(HAS_RAWTOYJROW_NEON) || defined(HAS_RAWTOYJROW_MSA) || \
3101     defined(HAS_RAWTOYJROW_RVV)
3102 #define HAS_RAWTOYJROW
3103 #endif
3104 
3105 // RAW to JNV21 full range NV21
3106 LIBYUV_API
RAWToJNV21(const uint8_t * src_raw,int src_stride_raw,uint8_t * dst_y,int dst_stride_y,uint8_t * dst_vu,int dst_stride_vu,int width,int height)3107 int RAWToJNV21(const uint8_t* src_raw,
3108                int src_stride_raw,
3109                uint8_t* dst_y,
3110                int dst_stride_y,
3111                uint8_t* dst_vu,
3112                int dst_stride_vu,
3113                int width,
3114                int height) {
3115   int y;
3116   int halfwidth = (width + 1) >> 1;
3117 #if defined(HAS_RAWTOYJROW)
3118   void (*RAWToUVJRow)(const uint8_t* src_raw, int src_stride_raw,
3119                       uint8_t* dst_uj, uint8_t* dst_vj, int width) =
3120       RAWToUVJRow_C;
3121   void (*RAWToYJRow)(const uint8_t* src_raw, uint8_t* dst_y, int width) =
3122       RAWToYJRow_C;
3123 #else
3124   void (*RAWToARGBRow)(const uint8_t* src_rgb, uint8_t* dst_argb, int width) =
3125       RAWToARGBRow_C;
3126   void (*ARGBToUVJRow)(const uint8_t* src_argb0, int src_stride_argb,
3127                        uint8_t* dst_uj, uint8_t* dst_vj, int width) =
3128       ARGBToUVJRow_C;
3129   void (*ARGBToYJRow)(const uint8_t* src_argb, uint8_t* dst_y, int width) =
3130       ARGBToYJRow_C;
3131 #endif
3132   void (*MergeUVRow_)(const uint8_t* src_uj, const uint8_t* src_vj,
3133                       uint8_t* dst_vu, int width) = MergeUVRow_C;
3134   if (!src_raw || !dst_y || !dst_vu || width <= 0 || height == 0) {
3135     return -1;
3136   }
3137   // Negative height means invert the image.
3138   if (height < 0) {
3139     height = -height;
3140     src_raw = src_raw + (height - 1) * src_stride_raw;
3141     src_stride_raw = -src_stride_raw;
3142   }
3143 
3144 #if defined(HAS_RAWTOYJROW)
3145 
3146 // Neon version does direct RAW to YUV.
3147 #if defined(HAS_RAWTOYJROW_NEON) && defined(HAS_RAWTOUVJROW_NEON)
3148   if (TestCpuFlag(kCpuHasNEON)) {
3149     RAWToUVJRow = RAWToUVJRow_Any_NEON;
3150     RAWToYJRow = RAWToYJRow_Any_NEON;
3151     if (IS_ALIGNED(width, 16)) {
3152       RAWToYJRow = RAWToYJRow_NEON;
3153       RAWToUVJRow = RAWToUVJRow_NEON;
3154     }
3155   }
3156 #endif
3157 #if defined(HAS_RAWTOYJROW_MSA) && defined(HAS_RAWTOUVJROW_MSA)
3158   if (TestCpuFlag(kCpuHasMSA)) {
3159     RAWToUVJRow = RAWToUVJRow_Any_MSA;
3160     RAWToYJRow = RAWToYJRow_Any_MSA;
3161     if (IS_ALIGNED(width, 16)) {
3162       RAWToYJRow = RAWToYJRow_MSA;
3163       RAWToUVJRow = RAWToUVJRow_MSA;
3164     }
3165   }
3166 #endif
3167 #if defined(HAS_RAWTOYJROW_LSX)
3168   if (TestCpuFlag(kCpuHasLSX)) {
3169     RAWToYJRow = RAWToYJRow_Any_LSX;
3170     if (IS_ALIGNED(width, 16)) {
3171       RAWToYJRow = RAWToYJRow_LSX;
3172     }
3173   }
3174 #endif
3175 #if defined(HAS_RAWTOYJROW_LASX)
3176   if (TestCpuFlag(kCpuHasLASX)) {
3177     RAWToYJRow = RAWToYJRow_Any_LASX;
3178     if (IS_ALIGNED(width, 32)) {
3179       RAWToYJRow = RAWToYJRow_LASX;
3180     }
3181   }
3182 #endif
3183 #if defined(HAS_RAWTOYJROW_RVV)
3184   if (TestCpuFlag(kCpuHasRVV)) {
3185     RAWToYJRow = RAWToYJRow_RVV;
3186   }
3187 #endif
3188 
3189 // Other platforms do intermediate conversion from RAW to ARGB.
3190 #else  // HAS_RAWTOYJROW
3191 
3192 #if defined(HAS_RAWTOARGBROW_SSSE3)
3193   if (TestCpuFlag(kCpuHasSSSE3)) {
3194     RAWToARGBRow = RAWToARGBRow_Any_SSSE3;
3195     if (IS_ALIGNED(width, 16)) {
3196       RAWToARGBRow = RAWToARGBRow_SSSE3;
3197     }
3198   }
3199 #endif
3200 #if defined(HAS_ARGBTOYJROW_SSSE3)
3201   if (TestCpuFlag(kCpuHasSSSE3)) {
3202     ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
3203     if (IS_ALIGNED(width, 16)) {
3204       ARGBToYJRow = ARGBToYJRow_SSSE3;
3205     }
3206   }
3207 #endif
3208 #if defined(HAS_ARGBTOYJROW_AVX2)
3209   if (TestCpuFlag(kCpuHasAVX2)) {
3210     ARGBToYJRow = ARGBToYJRow_Any_AVX2;
3211     if (IS_ALIGNED(width, 32)) {
3212       ARGBToYJRow = ARGBToYJRow_AVX2;
3213     }
3214   }
3215 #endif
3216 #if defined(HAS_ARGBTOUVJROW_SSSE3)
3217   if (TestCpuFlag(kCpuHasSSSE3)) {
3218     ARGBToUVJRow = ARGBToUVJRow_Any_SSSE3;
3219     if (IS_ALIGNED(width, 16)) {
3220       ARGBToUVJRow = ARGBToUVJRow_SSSE3;
3221     }
3222   }
3223 #endif
3224 #if defined(HAS_ARGBTOUVJROW_AVX2)
3225   if (TestCpuFlag(kCpuHasAVX2)) {
3226     ARGBToUVJRow = ARGBToUVJRow_Any_AVX2;
3227     if (IS_ALIGNED(width, 32)) {
3228       ARGBToUVJRow = ARGBToUVJRow_AVX2;
3229     }
3230   }
3231 #endif
3232 #endif  // HAS_RAWTOYJROW
3233 #if defined(HAS_MERGEUVROW_SSE2)
3234   if (TestCpuFlag(kCpuHasSSE2)) {
3235     MergeUVRow_ = MergeUVRow_Any_SSE2;
3236     if (IS_ALIGNED(halfwidth, 16)) {
3237       MergeUVRow_ = MergeUVRow_SSE2;
3238     }
3239   }
3240 #endif
3241 #if defined(HAS_MERGEUVROW_AVX2)
3242   if (TestCpuFlag(kCpuHasAVX2)) {
3243     MergeUVRow_ = MergeUVRow_Any_AVX2;
3244     if (IS_ALIGNED(halfwidth, 16)) {
3245       MergeUVRow_ = MergeUVRow_AVX2;
3246     }
3247   }
3248 #endif
3249 #if defined(HAS_MERGEUVROW_AVX512BW)
3250   if (TestCpuFlag(kCpuHasAVX512BW)) {
3251     MergeUVRow_ = MergeUVRow_Any_AVX512BW;
3252     if (IS_ALIGNED(halfwidth, 64)) {
3253       MergeUVRow_ = MergeUVRow_AVX512BW;
3254     }
3255   }
3256 #endif
3257 #if defined(HAS_MERGEUVROW_NEON)
3258   if (TestCpuFlag(kCpuHasNEON)) {
3259     MergeUVRow_ = MergeUVRow_Any_NEON;
3260     if (IS_ALIGNED(halfwidth, 16)) {
3261       MergeUVRow_ = MergeUVRow_NEON;
3262     }
3263   }
3264 #endif
3265 #if defined(HAS_MERGEUVROW_MSA)
3266   if (TestCpuFlag(kCpuHasMSA)) {
3267     MergeUVRow_ = MergeUVRow_Any_MSA;
3268     if (IS_ALIGNED(halfwidth, 16)) {
3269       MergeUVRow_ = MergeUVRow_MSA;
3270     }
3271   }
3272 #endif
3273 #if defined(HAS_MERGEUVROW_LSX)
3274   if (TestCpuFlag(kCpuHasLSX)) {
3275     MergeUVRow_ = MergeUVRow_Any_LSX;
3276     if (IS_ALIGNED(halfwidth, 16)) {
3277       MergeUVRow_ = MergeUVRow_LSX;
3278     }
3279   }
3280 #endif
3281 #if defined(HAS_MERGEUVROW_RVV)
3282   if (TestCpuFlag(kCpuHasRVV)) {
3283     MergeUVRow_ = MergeUVRow_RVV;
3284   }
3285 #endif
3286   {
3287 #if defined(HAS_RAWTOYJROW)
3288     // Allocate a row of uv.
3289     const int row_uv_size = ((halfwidth + 31) & ~31);
3290     align_buffer_64(row_uj, row_uv_size * 2);
3291     uint8_t* row_vj = row_uj + row_uv_size;
3292 #else
3293     // Allocate row of uv and 2 rows of ARGB.
3294     const int row_size = ((width * 4 + 31) & ~31);
3295     const int row_uv_size = ((halfwidth + 31) & ~31);
3296     align_buffer_64(row_uj, row_uv_size * 2 + row_size * 2);
3297     uint8_t* row_vj = row_uj + row_uv_size;
3298     uint8_t* row = row_vj + row_uv_size;
3299 #endif
3300     if (!row_uj)
3301       return 1;
3302 
3303     for (y = 0; y < height - 1; y += 2) {
3304 #if defined(HAS_RAWTOYJROW)
3305       RAWToUVJRow(src_raw, src_stride_raw, row_uj, row_vj, width);
3306       MergeUVRow_(row_vj, row_uj, dst_vu, halfwidth);
3307       RAWToYJRow(src_raw, dst_y, width);
3308       RAWToYJRow(src_raw + src_stride_raw, dst_y + dst_stride_y, width);
3309 #else
3310       RAWToARGBRow(src_raw, row, width);
3311       RAWToARGBRow(src_raw + src_stride_raw, row + row_size, width);
3312       ARGBToUVJRow(row, row_size, row_uj, row_vj, width);
3313       MergeUVRow_(row_vj, row_uj, dst_vu, halfwidth);
3314       ARGBToYJRow(row, dst_y, width);
3315       ARGBToYJRow(row + row_size, dst_y + dst_stride_y, width);
3316 #endif
3317       src_raw += src_stride_raw * 2;
3318       dst_y += dst_stride_y * 2;
3319       dst_vu += dst_stride_vu;
3320     }
3321     if (height & 1) {
3322 #if defined(HAS_RAWTOYJROW)
3323       RAWToUVJRow(src_raw, 0, row_uj, row_vj, width);
3324       MergeUVRow_(row_vj, row_uj, dst_vu, halfwidth);
3325       RAWToYJRow(src_raw, dst_y, width);
3326 #else
3327       RAWToARGBRow(src_raw, row, width);
3328       ARGBToUVJRow(row, 0, row_uj, row_vj, width);
3329       MergeUVRow_(row_vj, row_uj, dst_vu, halfwidth);
3330       ARGBToYJRow(row, dst_y, width);
3331 #endif
3332     }
3333     free_aligned_buffer_64(row_uj);
3334   }
3335   return 0;
3336 }
3337 #undef HAS_RAWTOYJROW
3338 
3339 #ifdef __cplusplus
3340 }  // extern "C"
3341 }  // namespace libyuv
3342 #endif
3343