2 * Copyright 2011 The LibYuv Project Authors. All rights reserved.
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.
11 #include "libyuv/convert_argb.h"
13 #include "libyuv/cpu_id.h"
14 #include "libyuv/format_conversion.h"
16 #include "libyuv/mjpeg_decoder.h"
18 #include "libyuv/rotate_argb.h"
19 #include "libyuv/row.h"
20 #include "libyuv/video_common.h"
27 // Copy ARGB with optional flipping
29 int ARGBCopy(const uint8* src_argb, int src_stride_argb,
30 uint8* dst_argb, int dst_stride_argb,
31 int width, int height) {
32 if (!src_argb || !dst_argb ||
33 width <= 0 || height == 0) {
36 // Negative height means invert the image.
39 src_argb = src_argb + (height - 1) * src_stride_argb;
40 src_stride_argb = -src_stride_argb;
43 CopyPlane(src_argb, src_stride_argb, dst_argb, dst_stride_argb,
48 // Convert I444 to ARGB.
50 int I444ToARGB(const uint8* src_y, int src_stride_y,
51 const uint8* src_u, int src_stride_u,
52 const uint8* src_v, int src_stride_v,
53 uint8* dst_argb, int dst_stride_argb,
54 int width, int height) {
56 void (*I444ToARGBRow)(const uint8* y_buf,
60 int width) = I444ToARGBRow_C;
61 if (!src_y || !src_u || !src_v ||
63 width <= 0 || height == 0) {
66 // Negative height means invert the image.
69 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
70 dst_stride_argb = -dst_stride_argb;
73 if (src_stride_y == width &&
74 src_stride_u == width &&
75 src_stride_v == width &&
76 dst_stride_argb == width * 4) {
79 src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
81 #if defined(HAS_I444TOARGBROW_SSSE3)
82 if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
83 I444ToARGBRow = I444ToARGBRow_Any_SSSE3;
84 if (IS_ALIGNED(width, 8)) {
85 I444ToARGBRow = I444ToARGBRow_Unaligned_SSSE3;
86 if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
87 I444ToARGBRow = I444ToARGBRow_SSSE3;
91 #elif defined(HAS_I444TOARGBROW_NEON)
92 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
93 I444ToARGBRow = I444ToARGBRow_Any_NEON;
94 if (IS_ALIGNED(width, 8)) {
95 I444ToARGBRow = I444ToARGBRow_NEON;
100 for (y = 0; y < height; ++y) {
101 I444ToARGBRow(src_y, src_u, src_v, dst_argb, width);
102 dst_argb += dst_stride_argb;
103 src_y += src_stride_y;
104 src_u += src_stride_u;
105 src_v += src_stride_v;
110 // Convert I422 to ARGB.
112 int I422ToARGB(const uint8* src_y, int src_stride_y,
113 const uint8* src_u, int src_stride_u,
114 const uint8* src_v, int src_stride_v,
115 uint8* dst_argb, int dst_stride_argb,
116 int width, int height) {
118 void (*I422ToARGBRow)(const uint8* y_buf,
122 int width) = I422ToARGBRow_C;
123 if (!src_y || !src_u || !src_v ||
125 width <= 0 || height == 0) {
128 // Negative height means invert the image.
131 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
132 dst_stride_argb = -dst_stride_argb;
135 if (src_stride_y == width &&
136 src_stride_u * 2 == width &&
137 src_stride_v * 2 == width &&
138 dst_stride_argb == width * 4) {
141 src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
143 #if defined(HAS_I422TOARGBROW_SSSE3)
144 if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
145 I422ToARGBRow = I422ToARGBRow_Any_SSSE3;
146 if (IS_ALIGNED(width, 8)) {
147 I422ToARGBRow = I422ToARGBRow_Unaligned_SSSE3;
148 if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
149 I422ToARGBRow = I422ToARGBRow_SSSE3;
154 #if defined(HAS_I422TOARGBROW_AVX2)
155 if (TestCpuFlag(kCpuHasAVX2) && width >= 16) {
156 I422ToARGBRow = I422ToARGBRow_Any_AVX2;
157 if (IS_ALIGNED(width, 16)) {
158 I422ToARGBRow = I422ToARGBRow_AVX2;
162 #if defined(HAS_I422TOARGBROW_NEON)
163 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
164 I422ToARGBRow = I422ToARGBRow_Any_NEON;
165 if (IS_ALIGNED(width, 8)) {
166 I422ToARGBRow = I422ToARGBRow_NEON;
170 #if defined(HAS_I422TOARGBROW_MIPS_DSPR2)
171 if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) &&
172 IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) &&
173 IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) &&
174 IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) &&
175 IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) {
176 I422ToARGBRow = I422ToARGBRow_MIPS_DSPR2;
180 for (y = 0; y < height; ++y) {
181 I422ToARGBRow(src_y, src_u, src_v, dst_argb, width);
182 dst_argb += dst_stride_argb;
183 src_y += src_stride_y;
184 src_u += src_stride_u;
185 src_v += src_stride_v;
190 // Convert I411 to ARGB.
192 int I411ToARGB(const uint8* src_y, int src_stride_y,
193 const uint8* src_u, int src_stride_u,
194 const uint8* src_v, int src_stride_v,
195 uint8* dst_argb, int dst_stride_argb,
196 int width, int height) {
198 void (*I411ToARGBRow)(const uint8* y_buf,
202 int width) = I411ToARGBRow_C;
203 if (!src_y || !src_u || !src_v ||
205 width <= 0 || height == 0) {
208 // Negative height means invert the image.
211 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
212 dst_stride_argb = -dst_stride_argb;
215 if (src_stride_y == width &&
216 src_stride_u * 4 == width &&
217 src_stride_v * 4 == width &&
218 dst_stride_argb == width * 4) {
221 src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0;
223 #if defined(HAS_I411TOARGBROW_SSSE3)
224 if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
225 I411ToARGBRow = I411ToARGBRow_Any_SSSE3;
226 if (IS_ALIGNED(width, 8)) {
227 I411ToARGBRow = I411ToARGBRow_Unaligned_SSSE3;
228 if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
229 I411ToARGBRow = I411ToARGBRow_SSSE3;
233 #elif defined(HAS_I411TOARGBROW_NEON)
234 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
235 I411ToARGBRow = I411ToARGBRow_Any_NEON;
236 if (IS_ALIGNED(width, 8)) {
237 I411ToARGBRow = I411ToARGBRow_NEON;
242 for (y = 0; y < height; ++y) {
243 I411ToARGBRow(src_y, src_u, src_v, dst_argb, width);
244 dst_argb += dst_stride_argb;
245 src_y += src_stride_y;
246 src_u += src_stride_u;
247 src_v += src_stride_v;
252 // Convert I400 to ARGB.
254 int I400ToARGB_Reference(const uint8* src_y, int src_stride_y,
255 uint8* dst_argb, int dst_stride_argb,
256 int width, int height) {
258 void (*YToARGBRow)(const uint8* y_buf,
260 int width) = YToARGBRow_C;
261 if (!src_y || !dst_argb ||
262 width <= 0 || height == 0) {
265 // Negative height means invert the image.
268 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
269 dst_stride_argb = -dst_stride_argb;
272 if (src_stride_y == width &&
273 dst_stride_argb == width * 4) {
276 src_stride_y = dst_stride_argb = 0;
278 #if defined(HAS_YTOARGBROW_SSE2)
279 if (TestCpuFlag(kCpuHasSSE2) && width >= 8 &&
280 IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
281 YToARGBRow = YToARGBRow_Any_SSE2;
282 if (IS_ALIGNED(width, 8)) {
283 YToARGBRow = YToARGBRow_SSE2;
286 #elif defined(HAS_YTOARGBROW_NEON)
287 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
288 YToARGBRow = YToARGBRow_Any_NEON;
289 if (IS_ALIGNED(width, 8)) {
290 YToARGBRow = YToARGBRow_NEON;
295 for (y = 0; y < height; ++y) {
296 YToARGBRow(src_y, dst_argb, width);
297 dst_argb += dst_stride_argb;
298 src_y += src_stride_y;
303 // Convert I400 to ARGB.
305 int I400ToARGB(const uint8* src_y, int src_stride_y,
306 uint8* dst_argb, int dst_stride_argb,
307 int width, int height) {
309 void (*I400ToARGBRow)(const uint8* src_y, uint8* dst_argb, int pix) =
311 if (!src_y || !dst_argb ||
312 width <= 0 || height == 0) {
315 // Negative height means invert the image.
318 src_y = src_y + (height - 1) * src_stride_y;
319 src_stride_y = -src_stride_y;
322 if (src_stride_y == width &&
323 dst_stride_argb == width * 4) {
326 src_stride_y = dst_stride_argb = 0;
328 #if defined(HAS_I400TOARGBROW_SSE2)
329 if (TestCpuFlag(kCpuHasSSE2) && width >= 8) {
330 I400ToARGBRow = I400ToARGBRow_Any_SSE2;
331 if (IS_ALIGNED(width, 8)) {
332 I400ToARGBRow = I400ToARGBRow_Unaligned_SSE2;
333 if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
334 I400ToARGBRow = I400ToARGBRow_SSE2;
338 #elif defined(HAS_I400TOARGBROW_NEON)
339 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
340 I400ToARGBRow = I400ToARGBRow_Any_NEON;
341 if (IS_ALIGNED(width, 8)) {
342 I400ToARGBRow = I400ToARGBRow_NEON;
346 for (y = 0; y < height; ++y) {
347 I400ToARGBRow(src_y, dst_argb, width);
348 src_y += src_stride_y;
349 dst_argb += dst_stride_argb;
354 // Shuffle table for converting BGRA to ARGB.
355 static uvec8 kShuffleMaskBGRAToARGB = {
356 3u, 2u, 1u, 0u, 7u, 6u, 5u, 4u, 11u, 10u, 9u, 8u, 15u, 14u, 13u, 12u
359 // Shuffle table for converting ABGR to ARGB.
360 static uvec8 kShuffleMaskABGRToARGB = {
361 2u, 1u, 0u, 3u, 6u, 5u, 4u, 7u, 10u, 9u, 8u, 11u, 14u, 13u, 12u, 15u
364 // Shuffle table for converting RGBA to ARGB.
365 static uvec8 kShuffleMaskRGBAToARGB = {
366 1u, 2u, 3u, 0u, 5u, 6u, 7u, 4u, 9u, 10u, 11u, 8u, 13u, 14u, 15u, 12u
369 // Convert BGRA to ARGB.
371 int BGRAToARGB(const uint8* src_bgra, int src_stride_bgra,
372 uint8* dst_argb, int dst_stride_argb,
373 int width, int height) {
374 return ARGBShuffle(src_bgra, src_stride_bgra,
375 dst_argb, dst_stride_argb,
376 (const uint8*)(&kShuffleMaskBGRAToARGB),
380 // Convert ARGB to BGRA (same as BGRAToARGB).
382 int ARGBToBGRA(const uint8* src_bgra, int src_stride_bgra,
383 uint8* dst_argb, int dst_stride_argb,
384 int width, int height) {
385 return ARGBShuffle(src_bgra, src_stride_bgra,
386 dst_argb, dst_stride_argb,
387 (const uint8*)(&kShuffleMaskBGRAToARGB),
391 // Convert ABGR to ARGB.
393 int ABGRToARGB(const uint8* src_abgr, int src_stride_abgr,
394 uint8* dst_argb, int dst_stride_argb,
395 int width, int height) {
396 return ARGBShuffle(src_abgr, src_stride_abgr,
397 dst_argb, dst_stride_argb,
398 (const uint8*)(&kShuffleMaskABGRToARGB),
402 // Convert ARGB to ABGR to (same as ABGRToARGB).
404 int ARGBToABGR(const uint8* src_abgr, int src_stride_abgr,
405 uint8* dst_argb, int dst_stride_argb,
406 int width, int height) {
407 return ARGBShuffle(src_abgr, src_stride_abgr,
408 dst_argb, dst_stride_argb,
409 (const uint8*)(&kShuffleMaskABGRToARGB),
413 // Convert RGBA to ARGB.
415 int RGBAToARGB(const uint8* src_rgba, int src_stride_rgba,
416 uint8* dst_argb, int dst_stride_argb,
417 int width, int height) {
418 return ARGBShuffle(src_rgba, src_stride_rgba,
419 dst_argb, dst_stride_argb,
420 (const uint8*)(&kShuffleMaskRGBAToARGB),
424 // Convert RGB24 to ARGB.
426 int RGB24ToARGB(const uint8* src_rgb24, int src_stride_rgb24,
427 uint8* dst_argb, int dst_stride_argb,
428 int width, int height) {
430 void (*RGB24ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) =
432 if (!src_rgb24 || !dst_argb ||
433 width <= 0 || height == 0) {
436 // Negative height means invert the image.
439 src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24;
440 src_stride_rgb24 = -src_stride_rgb24;
443 if (src_stride_rgb24 == width * 3 &&
444 dst_stride_argb == width * 4) {
447 src_stride_rgb24 = dst_stride_argb = 0;
449 #if defined(HAS_RGB24TOARGBROW_SSSE3)
450 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16 &&
451 IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
452 RGB24ToARGBRow = RGB24ToARGBRow_Any_SSSE3;
453 if (IS_ALIGNED(width, 16)) {
454 RGB24ToARGBRow = RGB24ToARGBRow_SSSE3;
457 #elif defined(HAS_RGB24TOARGBROW_NEON)
458 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
459 RGB24ToARGBRow = RGB24ToARGBRow_Any_NEON;
460 if (IS_ALIGNED(width, 8)) {
461 RGB24ToARGBRow = RGB24ToARGBRow_NEON;
466 for (y = 0; y < height; ++y) {
467 RGB24ToARGBRow(src_rgb24, dst_argb, width);
468 src_rgb24 += src_stride_rgb24;
469 dst_argb += dst_stride_argb;
474 // Convert RAW to ARGB.
476 int RAWToARGB(const uint8* src_raw, int src_stride_raw,
477 uint8* dst_argb, int dst_stride_argb,
478 int width, int height) {
480 void (*RAWToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) =
482 if (!src_raw || !dst_argb ||
483 width <= 0 || height == 0) {
486 // Negative height means invert the image.
489 src_raw = src_raw + (height - 1) * src_stride_raw;
490 src_stride_raw = -src_stride_raw;
493 if (src_stride_raw == width * 3 &&
494 dst_stride_argb == width * 4) {
497 src_stride_raw = dst_stride_argb = 0;
499 #if defined(HAS_RAWTOARGBROW_SSSE3)
500 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16 &&
501 IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
502 RAWToARGBRow = RAWToARGBRow_Any_SSSE3;
503 if (IS_ALIGNED(width, 16)) {
504 RAWToARGBRow = RAWToARGBRow_SSSE3;
507 #elif defined(HAS_RAWTOARGBROW_NEON)
508 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
509 RAWToARGBRow = RAWToARGBRow_Any_NEON;
510 if (IS_ALIGNED(width, 8)) {
511 RAWToARGBRow = RAWToARGBRow_NEON;
516 for (y = 0; y < height; ++y) {
517 RAWToARGBRow(src_raw, dst_argb, width);
518 src_raw += src_stride_raw;
519 dst_argb += dst_stride_argb;
524 // Convert RGB565 to ARGB.
526 int RGB565ToARGB(const uint8* src_rgb565, int src_stride_rgb565,
527 uint8* dst_argb, int dst_stride_argb,
528 int width, int height) {
530 void (*RGB565ToARGBRow)(const uint8* src_rgb565, uint8* dst_argb, int pix) =
532 if (!src_rgb565 || !dst_argb ||
533 width <= 0 || height == 0) {
536 // Negative height means invert the image.
539 src_rgb565 = src_rgb565 + (height - 1) * src_stride_rgb565;
540 src_stride_rgb565 = -src_stride_rgb565;
543 if (src_stride_rgb565 == width * 2 &&
544 dst_stride_argb == width * 4) {
547 src_stride_rgb565 = dst_stride_argb = 0;
549 #if defined(HAS_RGB565TOARGBROW_SSE2)
550 if (TestCpuFlag(kCpuHasSSE2) && width >= 8 &&
551 IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
552 RGB565ToARGBRow = RGB565ToARGBRow_Any_SSE2;
553 if (IS_ALIGNED(width, 8)) {
554 RGB565ToARGBRow = RGB565ToARGBRow_SSE2;
557 #elif defined(HAS_RGB565TOARGBROW_NEON)
558 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
559 RGB565ToARGBRow = RGB565ToARGBRow_Any_NEON;
560 if (IS_ALIGNED(width, 8)) {
561 RGB565ToARGBRow = RGB565ToARGBRow_NEON;
566 for (y = 0; y < height; ++y) {
567 RGB565ToARGBRow(src_rgb565, dst_argb, width);
568 src_rgb565 += src_stride_rgb565;
569 dst_argb += dst_stride_argb;
574 // Convert ARGB1555 to ARGB.
576 int ARGB1555ToARGB(const uint8* src_argb1555, int src_stride_argb1555,
577 uint8* dst_argb, int dst_stride_argb,
578 int width, int height) {
580 void (*ARGB1555ToARGBRow)(const uint8* src_argb1555, uint8* dst_argb,
581 int pix) = ARGB1555ToARGBRow_C;
582 if (!src_argb1555 || !dst_argb ||
583 width <= 0 || height == 0) {
586 // Negative height means invert the image.
589 src_argb1555 = src_argb1555 + (height - 1) * src_stride_argb1555;
590 src_stride_argb1555 = -src_stride_argb1555;
593 if (src_stride_argb1555 == width * 2 &&
594 dst_stride_argb == width * 4) {
597 src_stride_argb1555 = dst_stride_argb = 0;
599 #if defined(HAS_ARGB1555TOARGBROW_SSE2)
600 if (TestCpuFlag(kCpuHasSSE2) && width >= 8 &&
601 IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
602 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_SSE2;
603 if (IS_ALIGNED(width, 8)) {
604 ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2;
607 #elif defined(HAS_ARGB1555TOARGBROW_NEON)
608 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
609 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_NEON;
610 if (IS_ALIGNED(width, 8)) {
611 ARGB1555ToARGBRow = ARGB1555ToARGBRow_NEON;
616 for (y = 0; y < height; ++y) {
617 ARGB1555ToARGBRow(src_argb1555, dst_argb, width);
618 src_argb1555 += src_stride_argb1555;
619 dst_argb += dst_stride_argb;
624 // Convert ARGB4444 to ARGB.
626 int ARGB4444ToARGB(const uint8* src_argb4444, int src_stride_argb4444,
627 uint8* dst_argb, int dst_stride_argb,
628 int width, int height) {
630 void (*ARGB4444ToARGBRow)(const uint8* src_argb4444, uint8* dst_argb,
631 int pix) = ARGB4444ToARGBRow_C;
632 if (!src_argb4444 || !dst_argb ||
633 width <= 0 || height == 0) {
636 // Negative height means invert the image.
639 src_argb4444 = src_argb4444 + (height - 1) * src_stride_argb4444;
640 src_stride_argb4444 = -src_stride_argb4444;
643 if (src_stride_argb4444 == width * 2 &&
644 dst_stride_argb == width * 4) {
647 src_stride_argb4444 = dst_stride_argb = 0;
649 #if defined(HAS_ARGB4444TOARGBROW_SSE2)
650 if (TestCpuFlag(kCpuHasSSE2) && width >= 8 &&
651 IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
652 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_SSE2;
653 if (IS_ALIGNED(width, 8)) {
654 ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2;
657 #elif defined(HAS_ARGB4444TOARGBROW_NEON)
658 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
659 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_NEON;
660 if (IS_ALIGNED(width, 8)) {
661 ARGB4444ToARGBRow = ARGB4444ToARGBRow_NEON;
666 for (y = 0; y < height; ++y) {
667 ARGB4444ToARGBRow(src_argb4444, dst_argb, width);
668 src_argb4444 += src_stride_argb4444;
669 dst_argb += dst_stride_argb;
674 // Convert NV12 to ARGB.
676 int NV12ToARGB(const uint8* src_y, int src_stride_y,
677 const uint8* src_uv, int src_stride_uv,
678 uint8* dst_argb, int dst_stride_argb,
679 int width, int height) {
681 void (*NV12ToARGBRow)(const uint8* y_buf,
684 int width) = NV12ToARGBRow_C;
685 if (!src_y || !src_uv || !dst_argb ||
686 width <= 0 || height == 0) {
689 // Negative height means invert the image.
692 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
693 dst_stride_argb = -dst_stride_argb;
695 #if defined(HAS_NV12TOARGBROW_SSSE3)
696 if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
697 NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
698 if (IS_ALIGNED(width, 8)) {
699 NV12ToARGBRow = NV12ToARGBRow_Unaligned_SSSE3;
700 if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
701 NV12ToARGBRow = NV12ToARGBRow_SSSE3;
705 #elif defined(HAS_NV12TOARGBROW_NEON)
706 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
707 NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
708 if (IS_ALIGNED(width, 8)) {
709 NV12ToARGBRow = NV12ToARGBRow_NEON;
714 for (y = 0; y < height; ++y) {
715 NV12ToARGBRow(src_y, src_uv, dst_argb, width);
716 dst_argb += dst_stride_argb;
717 src_y += src_stride_y;
719 src_uv += src_stride_uv;
725 // Convert NV21 to ARGB.
727 int NV21ToARGB(const uint8* src_y, int src_stride_y,
728 const uint8* src_uv, int src_stride_uv,
729 uint8* dst_argb, int dst_stride_argb,
730 int width, int height) {
732 void (*NV21ToARGBRow)(const uint8* y_buf,
735 int width) = NV21ToARGBRow_C;
736 if (!src_y || !src_uv || !dst_argb ||
737 width <= 0 || height == 0) {
740 // Negative height means invert the image.
743 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
744 dst_stride_argb = -dst_stride_argb;
746 #if defined(HAS_NV21TOARGBROW_SSSE3)
747 if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
748 NV21ToARGBRow = NV21ToARGBRow_Any_SSSE3;
749 if (IS_ALIGNED(width, 8)) {
750 NV21ToARGBRow = NV21ToARGBRow_Unaligned_SSSE3;
751 if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
752 NV21ToARGBRow = NV21ToARGBRow_SSSE3;
757 #if defined(HAS_NV21TOARGBROW_NEON)
758 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
759 NV21ToARGBRow = NV21ToARGBRow_Any_NEON;
760 if (IS_ALIGNED(width, 8)) {
761 NV21ToARGBRow = NV21ToARGBRow_NEON;
766 for (y = 0; y < height; ++y) {
767 NV21ToARGBRow(src_y, src_uv, dst_argb, width);
768 dst_argb += dst_stride_argb;
769 src_y += src_stride_y;
771 src_uv += src_stride_uv;
777 // Convert M420 to ARGB.
779 int M420ToARGB(const uint8* src_m420, int src_stride_m420,
780 uint8* dst_argb, int dst_stride_argb,
781 int width, int height) {
783 void (*NV12ToARGBRow)(const uint8* y_buf,
786 int width) = NV12ToARGBRow_C;
787 if (!src_m420 || !dst_argb ||
788 width <= 0 || height == 0) {
791 // Negative height means invert the image.
794 dst_argb = dst_argb + (height - 1) * dst_stride_argb;
795 dst_stride_argb = -dst_stride_argb;
797 #if defined(HAS_NV12TOARGBROW_SSSE3)
798 if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) {
799 NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3;
800 if (IS_ALIGNED(width, 8)) {
801 NV12ToARGBRow = NV12ToARGBRow_Unaligned_SSSE3;
802 if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
803 NV12ToARGBRow = NV12ToARGBRow_SSSE3;
807 #elif defined(HAS_NV12TOARGBROW_NEON)
808 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
809 NV12ToARGBRow = NV12ToARGBRow_Any_NEON;
810 if (IS_ALIGNED(width, 8)) {
811 NV12ToARGBRow = NV12ToARGBRow_NEON;
816 for (y = 0; y < height - 1; y += 2) {
817 NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb, width);
818 NV12ToARGBRow(src_m420 + src_stride_m420, src_m420 + src_stride_m420 * 2,
819 dst_argb + dst_stride_argb, width);
820 dst_argb += dst_stride_argb * 2;
821 src_m420 += src_stride_m420 * 3;
824 NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb, width);
829 // Convert YUY2 to ARGB.
831 int YUY2ToARGB(const uint8* src_yuy2, int src_stride_yuy2,
832 uint8* dst_argb, int dst_stride_argb,
833 int width, int height) {
835 void (*YUY2ToARGBRow)(const uint8* src_yuy2, uint8* dst_argb, int pix) =
837 if (!src_yuy2 || !dst_argb ||
838 width <= 0 || height == 0) {
841 // Negative height means invert the image.
844 src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
845 src_stride_yuy2 = -src_stride_yuy2;
848 if (src_stride_yuy2 == width * 2 &&
849 dst_stride_argb == width * 4) {
852 src_stride_yuy2 = dst_stride_argb = 0;
854 #if defined(HAS_YUY2TOARGBROW_SSSE3)
855 // Posix is 16, Windows is 8.
856 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
857 YUY2ToARGBRow = YUY2ToARGBRow_Any_SSSE3;
858 if (IS_ALIGNED(width, 16)) {
859 YUY2ToARGBRow = YUY2ToARGBRow_Unaligned_SSSE3;
860 if (IS_ALIGNED(src_yuy2, 16) && IS_ALIGNED(src_stride_yuy2, 16) &&
861 IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
862 YUY2ToARGBRow = YUY2ToARGBRow_SSSE3;
866 #elif defined(HAS_YUY2TOARGBROW_NEON)
867 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
868 YUY2ToARGBRow = YUY2ToARGBRow_Any_NEON;
869 if (IS_ALIGNED(width, 8)) {
870 YUY2ToARGBRow = YUY2ToARGBRow_NEON;
874 for (y = 0; y < height; ++y) {
875 YUY2ToARGBRow(src_yuy2, dst_argb, width);
876 src_yuy2 += src_stride_yuy2;
877 dst_argb += dst_stride_argb;
882 // Convert UYVY to ARGB.
884 int UYVYToARGB(const uint8* src_uyvy, int src_stride_uyvy,
885 uint8* dst_argb, int dst_stride_argb,
886 int width, int height) {
888 void (*UYVYToARGBRow)(const uint8* src_uyvy, uint8* dst_argb, int pix) =
890 if (!src_uyvy || !dst_argb ||
891 width <= 0 || height == 0) {
894 // Negative height means invert the image.
897 src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
898 src_stride_uyvy = -src_stride_uyvy;
901 if (src_stride_uyvy == width * 2 &&
902 dst_stride_argb == width * 4) {
905 src_stride_uyvy = dst_stride_argb = 0;
907 #if defined(HAS_UYVYTOARGBROW_SSSE3)
908 // Posix is 16, Windows is 8.
909 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
910 UYVYToARGBRow = UYVYToARGBRow_Any_SSSE3;
911 if (IS_ALIGNED(width, 16)) {
912 UYVYToARGBRow = UYVYToARGBRow_Unaligned_SSSE3;
913 if (IS_ALIGNED(src_uyvy, 16) && IS_ALIGNED(src_stride_uyvy, 16) &&
914 IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
915 UYVYToARGBRow = UYVYToARGBRow_SSSE3;
919 #elif defined(HAS_UYVYTOARGBROW_NEON)
920 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
921 UYVYToARGBRow = UYVYToARGBRow_Any_NEON;
922 if (IS_ALIGNED(width, 8)) {
923 UYVYToARGBRow = UYVYToARGBRow_NEON;
927 for (y = 0; y < height; ++y) {
928 UYVYToARGBRow(src_uyvy, dst_argb, width);
929 src_uyvy += src_stride_uyvy;
930 dst_argb += dst_stride_argb;
937 } // namespace libyuv