Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / libyuv / source / convert_from_argb.cc
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/format_conversion.h"
16 #include "libyuv/planar_functions.h"
17 #include "libyuv/row.h"
18
19 #ifdef __cplusplus
20 namespace libyuv {
21 extern "C" {
22 #endif
23
24 // ARGB little endian (bgra in memory) to I444
25 LIBYUV_API
26 int ARGBToI444(const uint8* src_argb, int src_stride_argb,
27                uint8* dst_y, int dst_stride_y,
28                uint8* dst_u, int dst_stride_u,
29                uint8* dst_v, int dst_stride_v,
30                int width, int height) {
31   int y;
32   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
33       ARGBToYRow_C;
34   void (*ARGBToUV444Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v,
35       int pix) = ARGBToUV444Row_C;
36   if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
37     return -1;
38   }
39   if (height < 0) {
40     height = -height;
41     src_argb = src_argb + (height - 1) * src_stride_argb;
42     src_stride_argb = -src_stride_argb;
43   }
44   // Coalesce rows.
45   if (src_stride_argb == width * 4 &&
46       dst_stride_y == width &&
47       dst_stride_u == width &&
48       dst_stride_v == width) {
49     width *= height;
50     height = 1;
51     src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0;
52   }
53 #if defined(HAS_ARGBTOUV444ROW_SSSE3)
54     if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
55       ARGBToUV444Row = ARGBToUV444Row_Any_SSSE3;
56       if (IS_ALIGNED(width, 16)) {
57         ARGBToUV444Row = ARGBToUV444Row_Unaligned_SSSE3;
58         if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
59           ARGBToUV444Row = ARGBToUV444Row_SSSE3;
60         }
61       }
62   }
63 #endif
64 #if defined(HAS_ARGBTOYROW_SSSE3)
65   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
66     ARGBToYRow = ARGBToYRow_Any_SSSE3;
67     if (IS_ALIGNED(width, 16)) {
68       ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
69       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
70           IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
71         ARGBToYRow = ARGBToYRow_SSSE3;
72       }
73     }
74   }
75
76 #elif defined(HAS_ARGBTOYROW_NEON)
77   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
78     ARGBToYRow = ARGBToYRow_Any_NEON;
79     ARGBToUV444Row = ARGBToUV444Row_Any_NEON;
80     if (IS_ALIGNED(width, 8)) {
81       ARGBToYRow = ARGBToYRow_NEON;
82       ARGBToUV444Row = ARGBToUV444Row_NEON;
83     }
84   }
85 #endif
86
87   for (y = 0; y < height; ++y) {
88     ARGBToUV444Row(src_argb, dst_u, dst_v, width);
89     ARGBToYRow(src_argb, dst_y, width);
90     src_argb += src_stride_argb;
91     dst_y += dst_stride_y;
92     dst_u += dst_stride_u;
93     dst_v += dst_stride_v;
94   }
95   return 0;
96 }
97
98 // ARGB little endian (bgra in memory) to I422
99 LIBYUV_API
100 int ARGBToI422(const uint8* src_argb, int src_stride_argb,
101                uint8* dst_y, int dst_stride_y,
102                uint8* dst_u, int dst_stride_u,
103                uint8* dst_v, int dst_stride_v,
104                int width, int height) {
105   int y;
106   void (*ARGBToUV422Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v,
107       int pix) = ARGBToUV422Row_C;
108   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
109       ARGBToYRow_C;
110   if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
111     return -1;
112   }
113   if (height < 0) {
114     height = -height;
115     src_argb = src_argb + (height - 1) * src_stride_argb;
116     src_stride_argb = -src_stride_argb;
117   }
118   // Coalesce rows.
119   if (src_stride_argb == width * 4 &&
120       dst_stride_y == width &&
121       dst_stride_u * 2 == width &&
122       dst_stride_v * 2 == width) {
123     width *= height;
124     height = 1;
125     src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0;
126   }
127 #if defined(HAS_ARGBTOUV422ROW_SSSE3)
128   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
129     ARGBToUV422Row = ARGBToUV422Row_Any_SSSE3;
130     if (IS_ALIGNED(width, 16)) {
131       ARGBToUV422Row = ARGBToUV422Row_Unaligned_SSSE3;
132       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
133         ARGBToUV422Row = ARGBToUV422Row_SSSE3;
134       }
135     }
136   }
137 #endif
138
139 #if defined(HAS_ARGBTOYROW_SSSE3)
140   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
141     ARGBToYRow = ARGBToYRow_Any_SSSE3;
142     if (IS_ALIGNED(width, 16)) {
143       ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
144       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
145           IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
146         ARGBToYRow = ARGBToYRow_SSSE3;
147       }
148     }
149   }
150 #elif defined(HAS_ARGBTOYROW_NEON)
151   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
152     ARGBToYRow = ARGBToYRow_Any_NEON;
153     if (IS_ALIGNED(width, 8)) {
154       ARGBToYRow = ARGBToYRow_NEON;
155     }
156     if (width >= 16) {
157       ARGBToUV422Row = ARGBToUV422Row_Any_NEON;
158       if (IS_ALIGNED(width, 16)) {
159         ARGBToUV422Row = ARGBToUV422Row_NEON;
160       }
161     }
162   }
163 #endif
164
165   for (y = 0; y < height; ++y) {
166     ARGBToUV422Row(src_argb, dst_u, dst_v, width);
167     ARGBToYRow(src_argb, dst_y, width);
168     src_argb += src_stride_argb;
169     dst_y += dst_stride_y;
170     dst_u += dst_stride_u;
171     dst_v += dst_stride_v;
172   }
173   return 0;
174 }
175
176 // ARGB little endian (bgra in memory) to I411
177 LIBYUV_API
178 int ARGBToI411(const uint8* src_argb, int src_stride_argb,
179                uint8* dst_y, int dst_stride_y,
180                uint8* dst_u, int dst_stride_u,
181                uint8* dst_v, int dst_stride_v,
182                int width, int height) {
183   int y;
184   void (*ARGBToUV411Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v,
185       int pix) = ARGBToUV411Row_C;
186   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
187       ARGBToYRow_C;
188   if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) {
189     return -1;
190   }
191   if (height < 0) {
192     height = -height;
193     src_argb = src_argb + (height - 1) * src_stride_argb;
194     src_stride_argb = -src_stride_argb;
195   }
196   // Coalesce rows.
197   if (src_stride_argb == width * 4 &&
198       dst_stride_y == width &&
199       dst_stride_u * 4 == width &&
200       dst_stride_v * 4 == width) {
201     width *= height;
202     height = 1;
203     src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0;
204   }
205 #if defined(HAS_ARGBTOYROW_SSSE3)
206   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
207     ARGBToYRow = ARGBToYRow_Any_SSSE3;
208     if (IS_ALIGNED(width, 16)) {
209       ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
210       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
211           IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
212         ARGBToYRow = ARGBToYRow_SSSE3;
213       }
214     }
215   }
216 #endif
217 #if defined(HAS_ARGBTOYROW_AVX2)
218   if (TestCpuFlag(kCpuHasAVX2) && width >= 32) {
219     ARGBToYRow = ARGBToYRow_Any_AVX2;
220     if (IS_ALIGNED(width, 32)) {
221       ARGBToYRow = ARGBToYRow_AVX2;
222     }
223   }
224 #endif
225 #if defined(HAS_ARGBTOYROW_NEON)
226   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
227     ARGBToYRow = ARGBToYRow_Any_NEON;
228     if (IS_ALIGNED(width, 8)) {
229       ARGBToYRow = ARGBToYRow_NEON;
230     }
231     if (width >= 32) {
232       ARGBToUV411Row = ARGBToUV411Row_Any_NEON;
233       if (IS_ALIGNED(width, 32)) {
234         ARGBToUV411Row = ARGBToUV411Row_NEON;
235       }
236     }
237   }
238 #endif
239
240   for (y = 0; y < height; ++y) {
241     ARGBToUV411Row(src_argb, dst_u, dst_v, width);
242     ARGBToYRow(src_argb, dst_y, width);
243     src_argb += src_stride_argb;
244     dst_y += dst_stride_y;
245     dst_u += dst_stride_u;
246     dst_v += dst_stride_v;
247   }
248   return 0;
249 }
250
251 LIBYUV_API
252 int ARGBToNV12(const uint8* src_argb, int src_stride_argb,
253                uint8* dst_y, int dst_stride_y,
254                uint8* dst_uv, int dst_stride_uv,
255                int width, int height) {
256   int y;
257   int halfwidth = (width + 1) >> 1;
258   void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb,
259                       uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C;
260   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
261       ARGBToYRow_C;
262   void (*MergeUVRow_)(const uint8* src_u, const uint8* src_v, uint8* dst_uv,
263                       int width) = MergeUVRow_C;
264   // Allocate a rows of uv.
265   align_buffer_64(row_u, ((halfwidth + 15) & ~15) * 2);
266   uint8* row_v = row_u + ((halfwidth + 15) & ~15);
267   if (!src_argb ||
268       !dst_y || !dst_uv ||
269       width <= 0 || height == 0) {
270     return -1;
271   }
272   // Negative height means invert the image.
273   if (height < 0) {
274     height = -height;
275     src_argb = src_argb + (height - 1) * src_stride_argb;
276     src_stride_argb = -src_stride_argb;
277   }
278 #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
279   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
280     ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
281     ARGBToYRow = ARGBToYRow_Any_SSSE3;
282     if (IS_ALIGNED(width, 16)) {
283       ARGBToUVRow = ARGBToUVRow_Unaligned_SSSE3;
284       ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
285       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
286         ARGBToUVRow = ARGBToUVRow_SSSE3;
287         if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
288           ARGBToYRow = ARGBToYRow_SSSE3;
289         }
290       }
291     }
292   }
293 #elif defined(HAS_ARGBTOYROW_NEON)
294   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
295     ARGBToYRow = ARGBToYRow_Any_NEON;
296     if (IS_ALIGNED(width, 8)) {
297       ARGBToYRow = ARGBToYRow_NEON;
298     }
299     if (width >= 16) {
300       ARGBToUVRow = ARGBToUVRow_Any_NEON;
301       if (IS_ALIGNED(width, 16)) {
302         ARGBToUVRow = ARGBToUVRow_NEON;
303       }
304     }
305   }
306 #endif
307 #if defined(HAS_MERGEUVROW_SSE2)
308   if (TestCpuFlag(kCpuHasSSE2) && halfwidth >= 16) {
309     MergeUVRow_ = MergeUVRow_Any_SSE2;
310     if (IS_ALIGNED(halfwidth, 16)) {
311       MergeUVRow_ = MergeUVRow_Unaligned_SSE2;
312       if (IS_ALIGNED(dst_uv, 16) && IS_ALIGNED(dst_stride_uv, 16)) {
313         MergeUVRow_ = MergeUVRow_SSE2;
314       }
315     }
316   }
317 #endif
318 #if defined(HAS_MERGEUVROW_AVX2)
319   if (TestCpuFlag(kCpuHasAVX2) && halfwidth >= 32) {
320     MergeUVRow_ = MergeUVRow_Any_AVX2;
321     if (IS_ALIGNED(halfwidth, 32)) {
322       MergeUVRow_ = MergeUVRow_AVX2;
323     }
324   }
325 #endif
326 #if defined(HAS_MERGEUVROW_NEON)
327   if (TestCpuFlag(kCpuHasNEON) && halfwidth >= 16) {
328     MergeUVRow_ = MergeUVRow_Any_NEON;
329     if (IS_ALIGNED(halfwidth, 16)) {
330       MergeUVRow_ = MergeUVRow_NEON;
331     }
332   }
333 #endif
334
335   for (y = 0; y < height - 1; y += 2) {
336     ARGBToUVRow(src_argb, src_stride_argb, row_u, row_v, width);
337     MergeUVRow_(row_u, row_v, dst_uv, halfwidth);
338     ARGBToYRow(src_argb, dst_y, width);
339     ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width);
340     src_argb += src_stride_argb * 2;
341     dst_y += dst_stride_y * 2;
342     dst_uv += dst_stride_uv;
343   }
344   if (height & 1) {
345     ARGBToUVRow(src_argb, 0, row_u, row_v, width);
346     MergeUVRow_(row_u, row_v, dst_uv, halfwidth);
347     ARGBToYRow(src_argb, dst_y, width);
348   }
349   free_aligned_buffer_64(row_u);
350   return 0;
351 }
352
353 // Same as NV12 but U and V swapped.
354 LIBYUV_API
355 int ARGBToNV21(const uint8* src_argb, int src_stride_argb,
356                uint8* dst_y, int dst_stride_y,
357                uint8* dst_uv, int dst_stride_uv,
358                int width, int height) {
359   int y;
360   int halfwidth = (width + 1) >> 1;
361   void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb,
362                       uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C;
363   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
364       ARGBToYRow_C;
365   void (*MergeUVRow_)(const uint8* src_u, const uint8* src_v, uint8* dst_uv,
366                       int width) = MergeUVRow_C;
367   // Allocate a rows of uv.
368   align_buffer_64(row_u, ((halfwidth + 15) & ~15) * 2);
369   uint8* row_v = row_u + ((halfwidth + 15) & ~15);
370   if (!src_argb ||
371       !dst_y || !dst_uv ||
372       width <= 0 || height == 0) {
373     return -1;
374   }
375   // Negative height means invert the image.
376   if (height < 0) {
377     height = -height;
378     src_argb = src_argb + (height - 1) * src_stride_argb;
379     src_stride_argb = -src_stride_argb;
380   }
381 #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
382   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
383     ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
384     ARGBToYRow = ARGBToYRow_Any_SSSE3;
385     if (IS_ALIGNED(width, 16)) {
386       ARGBToUVRow = ARGBToUVRow_Unaligned_SSSE3;
387       ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
388       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
389         ARGBToUVRow = ARGBToUVRow_SSSE3;
390         if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
391           ARGBToYRow = ARGBToYRow_SSSE3;
392         }
393       }
394     }
395   }
396 #elif defined(HAS_ARGBTOYROW_NEON)
397   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
398     ARGBToYRow = ARGBToYRow_Any_NEON;
399     if (IS_ALIGNED(width, 8)) {
400       ARGBToYRow = ARGBToYRow_NEON;
401     }
402     if (width >= 16) {
403       ARGBToUVRow = ARGBToUVRow_Any_NEON;
404       if (IS_ALIGNED(width, 16)) {
405         ARGBToUVRow = ARGBToUVRow_NEON;
406       }
407     }
408   }
409 #endif
410 #if defined(HAS_MERGEUVROW_SSE2)
411   if (TestCpuFlag(kCpuHasSSE2) && halfwidth >= 16) {
412     MergeUVRow_ = MergeUVRow_Any_SSE2;
413     if (IS_ALIGNED(halfwidth, 16)) {
414       MergeUVRow_ = MergeUVRow_Unaligned_SSE2;
415       if (IS_ALIGNED(dst_uv, 16) && IS_ALIGNED(dst_stride_uv, 16)) {
416         MergeUVRow_ = MergeUVRow_SSE2;
417       }
418     }
419   }
420 #endif
421 #if defined(HAS_MERGEUVROW_AVX2)
422   if (TestCpuFlag(kCpuHasAVX2) && halfwidth >= 32) {
423     MergeUVRow_ = MergeUVRow_Any_AVX2;
424     if (IS_ALIGNED(halfwidth, 32)) {
425       MergeUVRow_ = MergeUVRow_AVX2;
426     }
427   }
428 #endif
429 #if defined(HAS_MERGEUVROW_NEON)
430   if (TestCpuFlag(kCpuHasNEON) && halfwidth >= 16) {
431     MergeUVRow_ = MergeUVRow_Any_NEON;
432     if (IS_ALIGNED(halfwidth, 16)) {
433       MergeUVRow_ = MergeUVRow_NEON;
434     }
435   }
436 #endif
437
438   for (y = 0; y < height - 1; y += 2) {
439     ARGBToUVRow(src_argb, src_stride_argb, row_u, row_v, width);
440     MergeUVRow_(row_v, row_u, dst_uv, halfwidth);
441     ARGBToYRow(src_argb, dst_y, width);
442     ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width);
443     src_argb += src_stride_argb * 2;
444     dst_y += dst_stride_y * 2;
445     dst_uv += dst_stride_uv;
446   }
447   if (height & 1) {
448     ARGBToUVRow(src_argb, 0, row_u, row_v, width);
449     MergeUVRow_(row_v, row_u, dst_uv, halfwidth);
450     ARGBToYRow(src_argb, dst_y, width);
451   }
452   free_aligned_buffer_64(row_u);
453   return 0;
454 }
455
456 // Convert ARGB to YUY2.
457 LIBYUV_API
458 int ARGBToYUY2(const uint8* src_argb, int src_stride_argb,
459                uint8* dst_yuy2, int dst_stride_yuy2,
460                int width, int height) {
461   int y;
462   void (*ARGBToUV422Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v,
463       int pix) = ARGBToUV422Row_C;
464   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
465       ARGBToYRow_C;
466   void (*I422ToYUY2Row)(const uint8* src_y, const uint8* src_u,
467       const uint8* src_v, uint8* dst_yuy2, int width) = I422ToYUY2Row_C;
468
469   if (!src_argb || !dst_yuy2 ||
470       width <= 0 || height == 0) {
471     return -1;
472   }
473   // Negative height means invert the image.
474   if (height < 0) {
475     height = -height;
476     dst_yuy2 = dst_yuy2 + (height - 1) * dst_stride_yuy2;
477     dst_stride_yuy2 = -dst_stride_yuy2;
478   }
479   // Coalesce rows.
480   if (src_stride_argb == width * 4 &&
481       dst_stride_yuy2 == width * 2) {
482     width *= height;
483     height = 1;
484     src_stride_argb = dst_stride_yuy2 = 0;
485   }
486 #if defined(HAS_ARGBTOUV422ROW_SSSE3)
487   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
488     ARGBToUV422Row = ARGBToUV422Row_Any_SSSE3;
489     if (IS_ALIGNED(width, 16)) {
490       ARGBToUV422Row = ARGBToUV422Row_Unaligned_SSSE3;
491       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
492         ARGBToUV422Row = ARGBToUV422Row_SSSE3;
493       }
494     }
495   }
496 #endif
497 #if defined(HAS_ARGBTOYROW_SSSE3)
498   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
499     ARGBToYRow = ARGBToYRow_Any_SSSE3;
500     if (IS_ALIGNED(width, 16)) {
501       ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
502       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
503         ARGBToYRow = ARGBToYRow_SSSE3;
504       }
505     }
506   }
507 #elif defined(HAS_ARGBTOYROW_NEON)
508   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
509     ARGBToYRow = ARGBToYRow_Any_NEON;
510     if (IS_ALIGNED(width, 8)) {
511       ARGBToYRow = ARGBToYRow_NEON;
512     }
513     if (width >= 16) {
514       ARGBToUV422Row = ARGBToUV422Row_Any_NEON;
515       if (IS_ALIGNED(width, 16)) {
516         ARGBToUV422Row = ARGBToUV422Row_NEON;
517       }
518     }
519   }
520 #endif
521
522 #if defined(HAS_I422TOYUY2ROW_SSE2)
523   if (TestCpuFlag(kCpuHasSSE2) && width >= 16) {
524     I422ToYUY2Row = I422ToYUY2Row_Any_SSE2;
525     if (IS_ALIGNED(width, 16)) {
526       I422ToYUY2Row = I422ToYUY2Row_SSE2;
527     }
528   }
529 #elif defined(HAS_I422TOYUY2ROW_NEON)
530   if (TestCpuFlag(kCpuHasNEON) && width >= 16) {
531     I422ToYUY2Row = I422ToYUY2Row_Any_NEON;
532     if (IS_ALIGNED(width, 16)) {
533       I422ToYUY2Row = I422ToYUY2Row_NEON;
534     }
535   }
536 #endif
537
538   {
539     // Allocate a rows of yuv.
540     align_buffer_64(row_y, ((width + 63) & ~63) * 2);
541     uint8* row_u = row_y + ((width + 63) & ~63);
542     uint8* row_v = row_u + ((width + 63) & ~63) / 2;
543
544     for (y = 0; y < height; ++y) {
545       ARGBToUV422Row(src_argb, row_u, row_v, width);
546       ARGBToYRow(src_argb, row_y, width);
547       I422ToYUY2Row(row_y, row_u, row_v, dst_yuy2, width);
548       src_argb += src_stride_argb;
549       dst_yuy2 += dst_stride_yuy2;
550     }
551
552     free_aligned_buffer_64(row_y);
553   }
554   return 0;
555 }
556
557 // Convert ARGB to UYVY.
558 LIBYUV_API
559 int ARGBToUYVY(const uint8* src_argb, int src_stride_argb,
560                uint8* dst_uyvy, int dst_stride_uyvy,
561                int width, int height) {
562   int y;
563   void (*ARGBToUV422Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v,
564       int pix) = ARGBToUV422Row_C;
565   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
566       ARGBToYRow_C;
567   void (*I422ToUYVYRow)(const uint8* src_y, const uint8* src_u,
568       const uint8* src_v, uint8* dst_uyvy, int width) = I422ToUYVYRow_C;
569
570   if (!src_argb || !dst_uyvy ||
571       width <= 0 || height == 0) {
572     return -1;
573   }
574   // Negative height means invert the image.
575   if (height < 0) {
576     height = -height;
577     dst_uyvy = dst_uyvy + (height - 1) * dst_stride_uyvy;
578     dst_stride_uyvy = -dst_stride_uyvy;
579   }
580   // Coalesce rows.
581   if (src_stride_argb == width * 4 &&
582       dst_stride_uyvy == width * 2) {
583     width *= height;
584     height = 1;
585     src_stride_argb = dst_stride_uyvy = 0;
586   }
587 #if defined(HAS_ARGBTOUV422ROW_SSSE3)
588   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
589     ARGBToUV422Row = ARGBToUV422Row_Any_SSSE3;
590     if (IS_ALIGNED(width, 16)) {
591       ARGBToUV422Row = ARGBToUV422Row_Unaligned_SSSE3;
592       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
593         ARGBToUV422Row = ARGBToUV422Row_SSSE3;
594       }
595     }
596   }
597 #endif
598 #if defined(HAS_ARGBTOYROW_SSSE3)
599   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
600     ARGBToYRow = ARGBToYRow_Any_SSSE3;
601     if (IS_ALIGNED(width, 16)) {
602       ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
603       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
604         ARGBToYRow = ARGBToYRow_SSSE3;
605       }
606     }
607   }
608 #elif defined(HAS_ARGBTOYROW_NEON)
609   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
610     ARGBToYRow = ARGBToYRow_Any_NEON;
611     if (IS_ALIGNED(width, 8)) {
612       ARGBToYRow = ARGBToYRow_NEON;
613     }
614     if (width >= 16) {
615       ARGBToUV422Row = ARGBToUV422Row_Any_NEON;
616       if (IS_ALIGNED(width, 16)) {
617         ARGBToUV422Row = ARGBToUV422Row_NEON;
618       }
619     }
620   }
621 #endif
622
623 #if defined(HAS_I422TOUYVYROW_SSE2)
624   if (TestCpuFlag(kCpuHasSSE2) && width >= 16) {
625     I422ToUYVYRow = I422ToUYVYRow_Any_SSE2;
626     if (IS_ALIGNED(width, 16)) {
627       I422ToUYVYRow = I422ToUYVYRow_SSE2;
628     }
629   }
630 #elif defined(HAS_I422TOUYVYROW_NEON)
631   if (TestCpuFlag(kCpuHasNEON) && width >= 16) {
632     I422ToUYVYRow = I422ToUYVYRow_Any_NEON;
633     if (IS_ALIGNED(width, 16)) {
634       I422ToUYVYRow = I422ToUYVYRow_NEON;
635     }
636   }
637 #endif
638
639   {
640     // Allocate a rows of yuv.
641     align_buffer_64(row_y, ((width + 63) & ~63) * 2);
642     uint8* row_u = row_y + ((width + 63) & ~63);
643     uint8* row_v = row_u + ((width + 63) & ~63) / 2;
644
645     for (y = 0; y < height; ++y) {
646       ARGBToUV422Row(src_argb, row_u, row_v, width);
647       ARGBToYRow(src_argb, row_y, width);
648       I422ToUYVYRow(row_y, row_u, row_v, dst_uyvy, width);
649       src_argb += src_stride_argb;
650       dst_uyvy += dst_stride_uyvy;
651     }
652
653     free_aligned_buffer_64(row_y);
654   }
655   return 0;
656 }
657
658 // Convert ARGB to I400.
659 LIBYUV_API
660 int ARGBToI400(const uint8* src_argb, int src_stride_argb,
661                uint8* dst_y, int dst_stride_y,
662                int width, int height) {
663   int y;
664   void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
665       ARGBToYRow_C;
666   if (!src_argb || !dst_y || width <= 0 || height == 0) {
667     return -1;
668   }
669   if (height < 0) {
670     height = -height;
671     src_argb = src_argb + (height - 1) * src_stride_argb;
672     src_stride_argb = -src_stride_argb;
673   }
674   // Coalesce rows.
675   if (src_stride_argb == width * 4 &&
676       dst_stride_y == width) {
677     width *= height;
678     height = 1;
679     src_stride_argb = dst_stride_y = 0;
680   }
681 #if defined(HAS_ARGBTOYROW_SSSE3)
682   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
683     ARGBToYRow = ARGBToYRow_Any_SSSE3;
684     if (IS_ALIGNED(width, 16)) {
685       ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
686       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
687           IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
688         ARGBToYRow = ARGBToYRow_SSSE3;
689       }
690     }
691   }
692 #endif
693 #if defined(HAS_ARGBTOYROW_AVX2)
694   if (TestCpuFlag(kCpuHasAVX2) && width >= 32) {
695     ARGBToYRow = ARGBToYRow_Any_AVX2;
696     if (IS_ALIGNED(width, 32)) {
697       ARGBToYRow = ARGBToYRow_AVX2;
698     }
699   }
700 #endif
701 #if defined(HAS_ARGBTOYROW_NEON)
702   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
703     ARGBToYRow = ARGBToYRow_Any_NEON;
704     if (IS_ALIGNED(width, 8)) {
705       ARGBToYRow = ARGBToYRow_NEON;
706     }
707   }
708 #endif
709
710   for (y = 0; y < height; ++y) {
711     ARGBToYRow(src_argb, dst_y, width);
712     src_argb += src_stride_argb;
713     dst_y += dst_stride_y;
714   }
715   return 0;
716 }
717
718 // Shuffle table for converting ARGB to RGBA.
719 static uvec8 kShuffleMaskARGBToRGBA = {
720   3u, 0u, 1u, 2u, 7u, 4u, 5u, 6u, 11u, 8u, 9u, 10u, 15u, 12u, 13u, 14u
721 };
722
723 // Convert ARGB to RGBA.
724 LIBYUV_API
725 int ARGBToRGBA(const uint8* src_argb, int src_stride_argb,
726                uint8* dst_rgba, int dst_stride_rgba,
727                int width, int height) {
728   return ARGBShuffle(src_argb, src_stride_argb,
729                      dst_rgba, dst_stride_rgba,
730                      (const uint8*)(&kShuffleMaskARGBToRGBA),
731                      width, height);
732 }
733
734 // Convert ARGB To RGB24.
735 LIBYUV_API
736 int ARGBToRGB24(const uint8* src_argb, int src_stride_argb,
737                 uint8* dst_rgb24, int dst_stride_rgb24,
738                 int width, int height) {
739   int y;
740   void (*ARGBToRGB24Row)(const uint8* src_argb, uint8* dst_rgb, int pix) =
741       ARGBToRGB24Row_C;
742   if (!src_argb || !dst_rgb24 || width <= 0 || height == 0) {
743     return -1;
744   }
745   if (height < 0) {
746     height = -height;
747     src_argb = src_argb + (height - 1) * src_stride_argb;
748     src_stride_argb = -src_stride_argb;
749   }
750   // Coalesce rows.
751   if (src_stride_argb == width * 4 &&
752       dst_stride_rgb24 == width * 3) {
753     width *= height;
754     height = 1;
755     src_stride_argb = dst_stride_rgb24 = 0;
756   }
757 #if defined(HAS_ARGBTORGB24ROW_SSSE3)
758   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
759     ARGBToRGB24Row = ARGBToRGB24Row_Any_SSSE3;
760     if (IS_ALIGNED(width, 16)) {
761       ARGBToRGB24Row = ARGBToRGB24Row_SSSE3;
762     }
763   }
764 #elif defined(HAS_ARGBTORGB24ROW_NEON)
765   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
766     ARGBToRGB24Row = ARGBToRGB24Row_Any_NEON;
767     if (IS_ALIGNED(width, 8)) {
768       ARGBToRGB24Row = ARGBToRGB24Row_NEON;
769     }
770   }
771 #endif
772
773   for (y = 0; y < height; ++y) {
774     ARGBToRGB24Row(src_argb, dst_rgb24, width);
775     src_argb += src_stride_argb;
776     dst_rgb24 += dst_stride_rgb24;
777   }
778   return 0;
779 }
780
781 // Convert ARGB To RAW.
782 LIBYUV_API
783 int ARGBToRAW(const uint8* src_argb, int src_stride_argb,
784               uint8* dst_raw, int dst_stride_raw,
785               int width, int height) {
786   int y;
787   void (*ARGBToRAWRow)(const uint8* src_argb, uint8* dst_rgb, int pix) =
788       ARGBToRAWRow_C;
789   if (!src_argb || !dst_raw || width <= 0 || height == 0) {
790     return -1;
791   }
792   if (height < 0) {
793     height = -height;
794     src_argb = src_argb + (height - 1) * src_stride_argb;
795     src_stride_argb = -src_stride_argb;
796   }
797   // Coalesce rows.
798   if (src_stride_argb == width * 4 &&
799       dst_stride_raw == width * 3) {
800     width *= height;
801     height = 1;
802     src_stride_argb = dst_stride_raw = 0;
803   }
804 #if defined(HAS_ARGBTORAWROW_SSSE3)
805   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
806     ARGBToRAWRow = ARGBToRAWRow_Any_SSSE3;
807     if (IS_ALIGNED(width, 16)) {
808       ARGBToRAWRow = ARGBToRAWRow_SSSE3;
809     }
810   }
811 #elif defined(HAS_ARGBTORAWROW_NEON)
812   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
813     ARGBToRAWRow = ARGBToRAWRow_Any_NEON;
814     if (IS_ALIGNED(width, 8)) {
815       ARGBToRAWRow = ARGBToRAWRow_NEON;
816     }
817   }
818 #endif
819
820   for (y = 0; y < height; ++y) {
821     ARGBToRAWRow(src_argb, dst_raw, width);
822     src_argb += src_stride_argb;
823     dst_raw += dst_stride_raw;
824   }
825   return 0;
826 }
827
828 // Convert ARGB To RGB565.
829 LIBYUV_API
830 int ARGBToRGB565(const uint8* src_argb, int src_stride_argb,
831                  uint8* dst_rgb565, int dst_stride_rgb565,
832                  int width, int height) {
833   int y;
834   void (*ARGBToRGB565Row)(const uint8* src_argb, uint8* dst_rgb, int pix) =
835       ARGBToRGB565Row_C;
836   if (!src_argb || !dst_rgb565 || width <= 0 || height == 0) {
837     return -1;
838   }
839   if (height < 0) {
840     height = -height;
841     src_argb = src_argb + (height - 1) * src_stride_argb;
842     src_stride_argb = -src_stride_argb;
843   }
844   // Coalesce rows.
845   if (src_stride_argb == width * 4 &&
846       dst_stride_rgb565 == width * 2) {
847     width *= height;
848     height = 1;
849     src_stride_argb = dst_stride_rgb565 = 0;
850   }
851 #if defined(HAS_ARGBTORGB565ROW_SSE2)
852   if (TestCpuFlag(kCpuHasSSE2) && width >= 4 &&
853       IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
854     ARGBToRGB565Row = ARGBToRGB565Row_Any_SSE2;
855     if (IS_ALIGNED(width, 4)) {
856       ARGBToRGB565Row = ARGBToRGB565Row_SSE2;
857     }
858   }
859 #elif defined(HAS_ARGBTORGB565ROW_NEON)
860   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
861     ARGBToRGB565Row = ARGBToRGB565Row_Any_NEON;
862     if (IS_ALIGNED(width, 8)) {
863       ARGBToRGB565Row = ARGBToRGB565Row_NEON;
864     }
865   }
866 #endif
867
868   for (y = 0; y < height; ++y) {
869     ARGBToRGB565Row(src_argb, dst_rgb565, width);
870     src_argb += src_stride_argb;
871     dst_rgb565 += dst_stride_rgb565;
872   }
873   return 0;
874 }
875
876 // Convert ARGB To ARGB1555.
877 LIBYUV_API
878 int ARGBToARGB1555(const uint8* src_argb, int src_stride_argb,
879                    uint8* dst_argb1555, int dst_stride_argb1555,
880                    int width, int height) {
881   int y;
882   void (*ARGBToARGB1555Row)(const uint8* src_argb, uint8* dst_rgb, int pix) =
883       ARGBToARGB1555Row_C;
884   if (!src_argb || !dst_argb1555 || width <= 0 || height == 0) {
885     return -1;
886   }
887   if (height < 0) {
888     height = -height;
889     src_argb = src_argb + (height - 1) * src_stride_argb;
890     src_stride_argb = -src_stride_argb;
891   }
892   // Coalesce rows.
893   if (src_stride_argb == width * 4 &&
894       dst_stride_argb1555 == width * 2) {
895     width *= height;
896     height = 1;
897     src_stride_argb = dst_stride_argb1555 = 0;
898   }
899 #if defined(HAS_ARGBTOARGB1555ROW_SSE2)
900   if (TestCpuFlag(kCpuHasSSE2) && width >= 4 &&
901       IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
902     ARGBToARGB1555Row = ARGBToARGB1555Row_Any_SSE2;
903     if (IS_ALIGNED(width, 4)) {
904       ARGBToARGB1555Row = ARGBToARGB1555Row_SSE2;
905     }
906   }
907 #elif defined(HAS_ARGBTOARGB1555ROW_NEON)
908   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
909     ARGBToARGB1555Row = ARGBToARGB1555Row_Any_NEON;
910     if (IS_ALIGNED(width, 8)) {
911       ARGBToARGB1555Row = ARGBToARGB1555Row_NEON;
912     }
913   }
914 #endif
915
916   for (y = 0; y < height; ++y) {
917     ARGBToARGB1555Row(src_argb, dst_argb1555, width);
918     src_argb += src_stride_argb;
919     dst_argb1555 += dst_stride_argb1555;
920   }
921   return 0;
922 }
923
924 // Convert ARGB To ARGB4444.
925 LIBYUV_API
926 int ARGBToARGB4444(const uint8* src_argb, int src_stride_argb,
927                    uint8* dst_argb4444, int dst_stride_argb4444,
928                    int width, int height) {
929   int y;
930   void (*ARGBToARGB4444Row)(const uint8* src_argb, uint8* dst_rgb, int pix) =
931       ARGBToARGB4444Row_C;
932   if (!src_argb || !dst_argb4444 || width <= 0 || height == 0) {
933     return -1;
934   }
935   if (height < 0) {
936     height = -height;
937     src_argb = src_argb + (height - 1) * src_stride_argb;
938     src_stride_argb = -src_stride_argb;
939   }
940   // Coalesce rows.
941   if (src_stride_argb == width * 4 &&
942       dst_stride_argb4444 == width * 2) {
943     width *= height;
944     height = 1;
945     src_stride_argb = dst_stride_argb4444 = 0;
946   }
947 #if defined(HAS_ARGBTOARGB4444ROW_SSE2)
948   if (TestCpuFlag(kCpuHasSSE2) && width >= 4 &&
949       IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
950     ARGBToARGB4444Row = ARGBToARGB4444Row_Any_SSE2;
951     if (IS_ALIGNED(width, 4)) {
952       ARGBToARGB4444Row = ARGBToARGB4444Row_SSE2;
953     }
954   }
955 #elif defined(HAS_ARGBTOARGB4444ROW_NEON)
956   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
957     ARGBToARGB4444Row = ARGBToARGB4444Row_Any_NEON;
958     if (IS_ALIGNED(width, 8)) {
959       ARGBToARGB4444Row = ARGBToARGB4444Row_NEON;
960     }
961   }
962 #endif
963
964   for (y = 0; y < height; ++y) {
965     ARGBToARGB4444Row(src_argb, dst_argb4444, width);
966     src_argb += src_stride_argb;
967     dst_argb4444 += dst_stride_argb4444;
968   }
969   return 0;
970 }
971
972 // Convert ARGB to J420. (JPeg full range I420).
973 LIBYUV_API
974 int ARGBToJ420(const uint8* src_argb, int src_stride_argb,
975                uint8* dst_yj, int dst_stride_yj,
976                uint8* dst_u, int dst_stride_u,
977                uint8* dst_v, int dst_stride_v,
978                int width, int height) {
979   int y;
980   void (*ARGBToUVJRow)(const uint8* src_argb0, int src_stride_argb,
981                       uint8* dst_u, uint8* dst_v, int width) = ARGBToUVJRow_C;
982   void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_yj, int pix) =
983       ARGBToYJRow_C;
984   if (!src_argb ||
985       !dst_yj || !dst_u || !dst_v ||
986       width <= 0 || height == 0) {
987     return -1;
988   }
989   // Negative height means invert the image.
990   if (height < 0) {
991     height = -height;
992     src_argb = src_argb + (height - 1) * src_stride_argb;
993     src_stride_argb = -src_stride_argb;
994   }
995 #if defined(HAS_ARGBTOYJROW_SSSE3) && defined(HAS_ARGBTOUVJROW_SSSE3)
996   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
997     ARGBToUVJRow = ARGBToUVJRow_Any_SSSE3;
998     ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
999     if (IS_ALIGNED(width, 16)) {
1000       ARGBToUVJRow = ARGBToUVJRow_Unaligned_SSSE3;
1001       ARGBToYJRow = ARGBToYJRow_Unaligned_SSSE3;
1002       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
1003         ARGBToUVJRow = ARGBToUVJRow_SSSE3;
1004         if (IS_ALIGNED(dst_yj, 16) && IS_ALIGNED(dst_stride_yj, 16)) {
1005           ARGBToYJRow = ARGBToYJRow_SSSE3;
1006         }
1007       }
1008     }
1009   }
1010 #endif
1011 #if defined(HAS_ARGBTOYJROW_AVX2) && defined(HAS_ARGBTOUVJROW_AVX2)
1012   if (TestCpuFlag(kCpuHasAVX2) && width >= 32) {
1013     ARGBToYJRow = ARGBToYJRow_Any_AVX2;
1014     if (IS_ALIGNED(width, 32)) {
1015       ARGBToYJRow = ARGBToYJRow_AVX2;
1016     }
1017   }
1018 #endif
1019 #if defined(HAS_ARGBTOYJROW_NEON)
1020   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
1021     ARGBToYJRow = ARGBToYJRow_Any_NEON;
1022     if (IS_ALIGNED(width, 8)) {
1023       ARGBToYJRow = ARGBToYJRow_NEON;
1024     }
1025     if (width >= 16) {
1026       ARGBToUVJRow = ARGBToUVJRow_Any_NEON;
1027       if (IS_ALIGNED(width, 16)) {
1028         ARGBToUVJRow = ARGBToUVJRow_NEON;
1029       }
1030     }
1031   }
1032 #endif
1033
1034   for (y = 0; y < height - 1; y += 2) {
1035     ARGBToUVJRow(src_argb, src_stride_argb, dst_u, dst_v, width);
1036     ARGBToYJRow(src_argb, dst_yj, width);
1037     ARGBToYJRow(src_argb + src_stride_argb, dst_yj + dst_stride_yj, width);
1038     src_argb += src_stride_argb * 2;
1039     dst_yj += dst_stride_yj * 2;
1040     dst_u += dst_stride_u;
1041     dst_v += dst_stride_v;
1042   }
1043   if (height & 1) {
1044     ARGBToUVJRow(src_argb, 0, dst_u, dst_v, width);
1045     ARGBToYJRow(src_argb, dst_yj, width);
1046   }
1047   return 0;
1048 }
1049
1050 // Convert ARGB to J400.
1051 LIBYUV_API
1052 int ARGBToJ400(const uint8* src_argb, int src_stride_argb,
1053                uint8* dst_yj, int dst_stride_yj,
1054                int width, int height) {
1055   int y;
1056   void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_yj, int pix) =
1057       ARGBToYJRow_C;
1058   if (!src_argb || !dst_yj || width <= 0 || height == 0) {
1059     return -1;
1060   }
1061   if (height < 0) {
1062     height = -height;
1063     src_argb = src_argb + (height - 1) * src_stride_argb;
1064     src_stride_argb = -src_stride_argb;
1065   }
1066   // Coalesce rows.
1067   if (src_stride_argb == width * 4 &&
1068       dst_stride_yj == width) {
1069     width *= height;
1070     height = 1;
1071     src_stride_argb = dst_stride_yj = 0;
1072   }
1073 #if defined(HAS_ARGBTOYJROW_SSSE3)
1074   if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
1075     ARGBToYJRow = ARGBToYJRow_Any_SSSE3;
1076     if (IS_ALIGNED(width, 16)) {
1077       ARGBToYJRow = ARGBToYJRow_Unaligned_SSSE3;
1078       if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
1079           IS_ALIGNED(dst_yj, 16) && IS_ALIGNED(dst_stride_yj, 16)) {
1080         ARGBToYJRow = ARGBToYJRow_SSSE3;
1081       }
1082     }
1083   }
1084 #endif
1085 #if defined(HAS_ARGBTOYJROW_AVX2)
1086   if (TestCpuFlag(kCpuHasAVX2) && width >= 32) {
1087     ARGBToYJRow = ARGBToYJRow_Any_AVX2;
1088     if (IS_ALIGNED(width, 32)) {
1089       ARGBToYJRow = ARGBToYJRow_AVX2;
1090     }
1091   }
1092 #endif
1093 #if defined(HAS_ARGBTOYJROW_NEON)
1094   if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
1095     ARGBToYJRow = ARGBToYJRow_Any_NEON;
1096     if (IS_ALIGNED(width, 8)) {
1097       ARGBToYJRow = ARGBToYJRow_NEON;
1098     }
1099   }
1100 #endif
1101
1102   for (y = 0; y < height; ++y) {
1103     ARGBToYJRow(src_argb, dst_yj, width);
1104     src_argb += src_stride_argb;
1105     dst_yj += dst_stride_yj;
1106   }
1107   return 0;
1108 }
1109
1110 #ifdef __cplusplus
1111 }  // extern "C"
1112 }  // namespace libyuv
1113 #endif