1 /* 2 * Copyright 2011 The LibYuv Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "libyuv/convert_argb.h" 12 13 #include "libyuv/cpu_id.h" 14 #include "libyuv/format_conversion.h" 15 #ifdef HAVE_JPEG 16 #include "libyuv/mjpeg_decoder.h" 17 #endif 18 #include "libyuv/rotate_argb.h" 19 #include "libyuv/row.h" 20 #include "libyuv/video_common.h" 21 22 #ifdef __cplusplus 23 namespace libyuv { 24 extern "C" { 25 #endif 26 27 // Copy ARGB with optional flipping 28 LIBYUV_API 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) { 34 return -1; 35 } 36 // Negative height means invert the image. 37 if (height < 0) { 38 height = -height; 39 src_argb = src_argb + (height - 1) * src_stride_argb; 40 src_stride_argb = -src_stride_argb; 41 } 42 43 CopyPlane(src_argb, src_stride_argb, dst_argb, dst_stride_argb, 44 width * 4, height); 45 return 0; 46 } 47 48 // Convert I444 to ARGB. 49 LIBYUV_API 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) { 55 int y; 56 void (*I444ToARGBRow)(const uint8* y_buf, 57 const uint8* u_buf, 58 const uint8* v_buf, 59 uint8* rgb_buf, 60 int width) = I444ToARGBRow_C; 61 if (!src_y || !src_u || !src_v || 62 !dst_argb || 63 width <= 0 || height == 0) { 64 return -1; 65 } 66 // Negative height means invert the image. 67 if (height < 0) { 68 height = -height; 69 dst_argb = dst_argb + (height - 1) * dst_stride_argb; 70 dst_stride_argb = -dst_stride_argb; 71 } 72 // Coalesce rows. 73 if (src_stride_y == width && 74 src_stride_u == width && 75 src_stride_v == width && 76 dst_stride_argb == width * 4) { 77 width *= height; 78 height = 1; 79 src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0; 80 } 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; 88 } 89 } 90 } 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; 96 } 97 } 98 #endif 99 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; 106 } 107 return 0; 108 } 109 110 // Convert I422 to ARGB. 111 LIBYUV_API 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) { 117 int y; 118 void (*I422ToARGBRow)(const uint8* y_buf, 119 const uint8* u_buf, 120 const uint8* v_buf, 121 uint8* rgb_buf, 122 int width) = I422ToARGBRow_C; 123 if (!src_y || !src_u || !src_v || 124 !dst_argb || 125 width <= 0 || height == 0) { 126 return -1; 127 } 128 // Negative height means invert the image. 129 if (height < 0) { 130 height = -height; 131 dst_argb = dst_argb + (height - 1) * dst_stride_argb; 132 dst_stride_argb = -dst_stride_argb; 133 } 134 // Coalesce rows. 135 if (src_stride_y == width && 136 src_stride_u * 2 == width && 137 src_stride_v * 2 == width && 138 dst_stride_argb == width * 4) { 139 width *= height; 140 height = 1; 141 src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0; 142 } 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; 150 } 151 } 152 } 153 #endif 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; 159 } 160 } 161 #endif 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; 167 } 168 } 169 #endif 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; 177 } 178 #endif 179 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; 186 } 187 return 0; 188 } 189 190 // Convert I411 to ARGB. 191 LIBYUV_API 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) { 197 int y; 198 void (*I411ToARGBRow)(const uint8* y_buf, 199 const uint8* u_buf, 200 const uint8* v_buf, 201 uint8* rgb_buf, 202 int width) = I411ToARGBRow_C; 203 if (!src_y || !src_u || !src_v || 204 !dst_argb || 205 width <= 0 || height == 0) { 206 return -1; 207 } 208 // Negative height means invert the image. 209 if (height < 0) { 210 height = -height; 211 dst_argb = dst_argb + (height - 1) * dst_stride_argb; 212 dst_stride_argb = -dst_stride_argb; 213 } 214 // Coalesce rows. 215 if (src_stride_y == width && 216 src_stride_u * 4 == width && 217 src_stride_v * 4 == width && 218 dst_stride_argb == width * 4) { 219 width *= height; 220 height = 1; 221 src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0; 222 } 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; 230 } 231 } 232 } 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; 238 } 239 } 240 #endif 241 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; 248 } 249 return 0; 250 } 251 252 // Convert I400 to ARGB. 253 LIBYUV_API 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) { 257 int y; 258 void (*YToARGBRow)(const uint8* y_buf, 259 uint8* rgb_buf, 260 int width) = YToARGBRow_C; 261 if (!src_y || !dst_argb || 262 width <= 0 || height == 0) { 263 return -1; 264 } 265 // Negative height means invert the image. 266 if (height < 0) { 267 height = -height; 268 dst_argb = dst_argb + (height - 1) * dst_stride_argb; 269 dst_stride_argb = -dst_stride_argb; 270 } 271 // Coalesce rows. 272 if (src_stride_y == width && 273 dst_stride_argb == width * 4) { 274 width *= height; 275 height = 1; 276 src_stride_y = dst_stride_argb = 0; 277 } 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; 284 } 285 } 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; 291 } 292 } 293 #endif 294 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; 299 } 300 return 0; 301 } 302 303 // Convert I400 to ARGB. 304 LIBYUV_API 305 int I400ToARGB(const uint8* src_y, int src_stride_y, 306 uint8* dst_argb, int dst_stride_argb, 307 int width, int height) { 308 int y; 309 void (*I400ToARGBRow)(const uint8* src_y, uint8* dst_argb, int pix) = 310 I400ToARGBRow_C; 311 if (!src_y || !dst_argb || 312 width <= 0 || height == 0) { 313 return -1; 314 } 315 // Negative height means invert the image. 316 if (height < 0) { 317 height = -height; 318 src_y = src_y + (height - 1) * src_stride_y; 319 src_stride_y = -src_stride_y; 320 } 321 // Coalesce rows. 322 if (src_stride_y == width && 323 dst_stride_argb == width * 4) { 324 width *= height; 325 height = 1; 326 src_stride_y = dst_stride_argb = 0; 327 } 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; 335 } 336 } 337 } 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; 343 } 344 } 345 #endif 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; 350 } 351 return 0; 352 } 353 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 357 }; 358 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 362 }; 363 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 367 }; 368 369 // Convert BGRA to ARGB. 370 LIBYUV_API 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), 377 width, height); 378 } 379 380 // Convert ARGB to BGRA (same as BGRAToARGB). 381 LIBYUV_API 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), 388 width, height); 389 } 390 391 // Convert ABGR to ARGB. 392 LIBYUV_API 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), 399 width, height); 400 } 401 402 // Convert ARGB to ABGR to (same as ABGRToARGB). 403 LIBYUV_API 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), 410 width, height); 411 } 412 413 // Convert RGBA to ARGB. 414 LIBYUV_API 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), 421 width, height); 422 } 423 424 // Convert RGB24 to ARGB. 425 LIBYUV_API 426 int RGB24ToARGB(const uint8* src_rgb24, int src_stride_rgb24, 427 uint8* dst_argb, int dst_stride_argb, 428 int width, int height) { 429 int y; 430 void (*RGB24ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) = 431 RGB24ToARGBRow_C; 432 if (!src_rgb24 || !dst_argb || 433 width <= 0 || height == 0) { 434 return -1; 435 } 436 // Negative height means invert the image. 437 if (height < 0) { 438 height = -height; 439 src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24; 440 src_stride_rgb24 = -src_stride_rgb24; 441 } 442 // Coalesce rows. 443 if (src_stride_rgb24 == width * 3 && 444 dst_stride_argb == width * 4) { 445 width *= height; 446 height = 1; 447 src_stride_rgb24 = dst_stride_argb = 0; 448 } 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; 455 } 456 } 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; 462 } 463 } 464 #endif 465 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; 470 } 471 return 0; 472 } 473 474 // Convert RAW to ARGB. 475 LIBYUV_API 476 int RAWToARGB(const uint8* src_raw, int src_stride_raw, 477 uint8* dst_argb, int dst_stride_argb, 478 int width, int height) { 479 int y; 480 void (*RAWToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) = 481 RAWToARGBRow_C; 482 if (!src_raw || !dst_argb || 483 width <= 0 || height == 0) { 484 return -1; 485 } 486 // Negative height means invert the image. 487 if (height < 0) { 488 height = -height; 489 src_raw = src_raw + (height - 1) * src_stride_raw; 490 src_stride_raw = -src_stride_raw; 491 } 492 // Coalesce rows. 493 if (src_stride_raw == width * 3 && 494 dst_stride_argb == width * 4) { 495 width *= height; 496 height = 1; 497 src_stride_raw = dst_stride_argb = 0; 498 } 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; 505 } 506 } 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; 512 } 513 } 514 #endif 515 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; 520 } 521 return 0; 522 } 523 524 // Convert RGB565 to ARGB. 525 LIBYUV_API 526 int RGB565ToARGB(const uint8* src_rgb565, int src_stride_rgb565, 527 uint8* dst_argb, int dst_stride_argb, 528 int width, int height) { 529 int y; 530 void (*RGB565ToARGBRow)(const uint8* src_rgb565, uint8* dst_argb, int pix) = 531 RGB565ToARGBRow_C; 532 if (!src_rgb565 || !dst_argb || 533 width <= 0 || height == 0) { 534 return -1; 535 } 536 // Negative height means invert the image. 537 if (height < 0) { 538 height = -height; 539 src_rgb565 = src_rgb565 + (height - 1) * src_stride_rgb565; 540 src_stride_rgb565 = -src_stride_rgb565; 541 } 542 // Coalesce rows. 543 if (src_stride_rgb565 == width * 2 && 544 dst_stride_argb == width * 4) { 545 width *= height; 546 height = 1; 547 src_stride_rgb565 = dst_stride_argb = 0; 548 } 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; 555 } 556 } 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; 562 } 563 } 564 #endif 565 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; 570 } 571 return 0; 572 } 573 574 // Convert ARGB1555 to ARGB. 575 LIBYUV_API 576 int ARGB1555ToARGB(const uint8* src_argb1555, int src_stride_argb1555, 577 uint8* dst_argb, int dst_stride_argb, 578 int width, int height) { 579 int y; 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) { 584 return -1; 585 } 586 // Negative height means invert the image. 587 if (height < 0) { 588 height = -height; 589 src_argb1555 = src_argb1555 + (height - 1) * src_stride_argb1555; 590 src_stride_argb1555 = -src_stride_argb1555; 591 } 592 // Coalesce rows. 593 if (src_stride_argb1555 == width * 2 && 594 dst_stride_argb == width * 4) { 595 width *= height; 596 height = 1; 597 src_stride_argb1555 = dst_stride_argb = 0; 598 } 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; 605 } 606 } 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; 612 } 613 } 614 #endif 615 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; 620 } 621 return 0; 622 } 623 624 // Convert ARGB4444 to ARGB. 625 LIBYUV_API 626 int ARGB4444ToARGB(const uint8* src_argb4444, int src_stride_argb4444, 627 uint8* dst_argb, int dst_stride_argb, 628 int width, int height) { 629 int y; 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) { 634 return -1; 635 } 636 // Negative height means invert the image. 637 if (height < 0) { 638 height = -height; 639 src_argb4444 = src_argb4444 + (height - 1) * src_stride_argb4444; 640 src_stride_argb4444 = -src_stride_argb4444; 641 } 642 // Coalesce rows. 643 if (src_stride_argb4444 == width * 2 && 644 dst_stride_argb == width * 4) { 645 width *= height; 646 height = 1; 647 src_stride_argb4444 = dst_stride_argb = 0; 648 } 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; 655 } 656 } 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; 662 } 663 } 664 #endif 665 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; 670 } 671 return 0; 672 } 673 674 // Convert NV12 to ARGB. 675 LIBYUV_API 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) { 680 int y; 681 void (*NV12ToARGBRow)(const uint8* y_buf, 682 const uint8* uv_buf, 683 uint8* rgb_buf, 684 int width) = NV12ToARGBRow_C; 685 if (!src_y || !src_uv || !dst_argb || 686 width <= 0 || height == 0) { 687 return -1; 688 } 689 // Negative height means invert the image. 690 if (height < 0) { 691 height = -height; 692 dst_argb = dst_argb + (height - 1) * dst_stride_argb; 693 dst_stride_argb = -dst_stride_argb; 694 } 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; 702 } 703 } 704 } 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; 710 } 711 } 712 #endif 713 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; 718 if (y & 1) { 719 src_uv += src_stride_uv; 720 } 721 } 722 return 0; 723 } 724 725 // Convert NV21 to ARGB. 726 LIBYUV_API 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) { 731 int y; 732 void (*NV21ToARGBRow)(const uint8* y_buf, 733 const uint8* uv_buf, 734 uint8* rgb_buf, 735 int width) = NV21ToARGBRow_C; 736 if (!src_y || !src_uv || !dst_argb || 737 width <= 0 || height == 0) { 738 return -1; 739 } 740 // Negative height means invert the image. 741 if (height < 0) { 742 height = -height; 743 dst_argb = dst_argb + (height - 1) * dst_stride_argb; 744 dst_stride_argb = -dst_stride_argb; 745 } 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; 753 } 754 } 755 } 756 #endif 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; 762 } 763 } 764 #endif 765 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; 770 if (y & 1) { 771 src_uv += src_stride_uv; 772 } 773 } 774 return 0; 775 } 776 777 // Convert M420 to ARGB. 778 LIBYUV_API 779 int M420ToARGB(const uint8* src_m420, int src_stride_m420, 780 uint8* dst_argb, int dst_stride_argb, 781 int width, int height) { 782 int y; 783 void (*NV12ToARGBRow)(const uint8* y_buf, 784 const uint8* uv_buf, 785 uint8* rgb_buf, 786 int width) = NV12ToARGBRow_C; 787 if (!src_m420 || !dst_argb || 788 width <= 0 || height == 0) { 789 return -1; 790 } 791 // Negative height means invert the image. 792 if (height < 0) { 793 height = -height; 794 dst_argb = dst_argb + (height - 1) * dst_stride_argb; 795 dst_stride_argb = -dst_stride_argb; 796 } 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; 804 } 805 } 806 } 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; 812 } 813 } 814 #endif 815 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; 822 } 823 if (height & 1) { 824 NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb, width); 825 } 826 return 0; 827 } 828 829 // Convert YUY2 to ARGB. 830 LIBYUV_API 831 int YUY2ToARGB(const uint8* src_yuy2, int src_stride_yuy2, 832 uint8* dst_argb, int dst_stride_argb, 833 int width, int height) { 834 int y; 835 void (*YUY2ToARGBRow)(const uint8* src_yuy2, uint8* dst_argb, int pix) = 836 YUY2ToARGBRow_C; 837 if (!src_yuy2 || !dst_argb || 838 width <= 0 || height == 0) { 839 return -1; 840 } 841 // Negative height means invert the image. 842 if (height < 0) { 843 height = -height; 844 src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2; 845 src_stride_yuy2 = -src_stride_yuy2; 846 } 847 // Coalesce rows. 848 if (src_stride_yuy2 == width * 2 && 849 dst_stride_argb == width * 4) { 850 width *= height; 851 height = 1; 852 src_stride_yuy2 = dst_stride_argb = 0; 853 } 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; 863 } 864 } 865 } 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; 871 } 872 } 873 #endif 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; 878 } 879 return 0; 880 } 881 882 // Convert UYVY to ARGB. 883 LIBYUV_API 884 int UYVYToARGB(const uint8* src_uyvy, int src_stride_uyvy, 885 uint8* dst_argb, int dst_stride_argb, 886 int width, int height) { 887 int y; 888 void (*UYVYToARGBRow)(const uint8* src_uyvy, uint8* dst_argb, int pix) = 889 UYVYToARGBRow_C; 890 if (!src_uyvy || !dst_argb || 891 width <= 0 || height == 0) { 892 return -1; 893 } 894 // Negative height means invert the image. 895 if (height < 0) { 896 height = -height; 897 src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy; 898 src_stride_uyvy = -src_stride_uyvy; 899 } 900 // Coalesce rows. 901 if (src_stride_uyvy == width * 2 && 902 dst_stride_argb == width * 4) { 903 width *= height; 904 height = 1; 905 src_stride_uyvy = dst_stride_argb = 0; 906 } 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; 916 } 917 } 918 } 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; 924 } 925 } 926 #endif 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; 931 } 932 return 0; 933 } 934 935 #ifdef __cplusplus 936 } // extern "C" 937 } // namespace libyuv 938 #endif 939