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