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#ifdef HAVE_JPEG 15#include "libyuv/mjpeg_decoder.h" 16#endif 17#include "libyuv/planar_functions.h" // For CopyPlane and ARGBShuffle. 18#include "libyuv/rotate_argb.h" 19#include "libyuv/row.h" 20#include "libyuv/video_common.h" 21 22#ifdef __cplusplus 23namespace libyuv { 24extern "C" { 25#endif 26 27// Copy ARGB with optional flipping 28LIBYUV_API 29int ARGBCopy(const uint8* src_argb, 30 int src_stride_argb, 31 uint8* dst_argb, 32 int dst_stride_argb, 33 int width, 34 int height) { 35 if (!src_argb || !dst_argb || width <= 0 || height == 0) { 36 return -1; 37 } 38 // Negative height means invert the image. 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 45 CopyPlane(src_argb, src_stride_argb, dst_argb, dst_stride_argb, width * 4, 46 height); 47 return 0; 48} 49 50// Convert I422 to ARGB with matrix 51static int I420ToARGBMatrix(const uint8* src_y, 52 int src_stride_y, 53 const uint8* src_u, 54 int src_stride_u, 55 const uint8* src_v, 56 int src_stride_v, 57 uint8* dst_argb, 58 int dst_stride_argb, 59 const struct YuvConstants* yuvconstants, 60 int width, 61 int height) { 62 int y; 63 void (*I422ToARGBRow)(const uint8* y_buf, const uint8* u_buf, 64 const uint8* v_buf, uint8* rgb_buf, 65 const struct YuvConstants* yuvconstants, int width) = 66 I422ToARGBRow_C; 67 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) { 68 return -1; 69 } 70 // Negative height means invert the image. 71 if (height < 0) { 72 height = -height; 73 dst_argb = dst_argb + (height - 1) * dst_stride_argb; 74 dst_stride_argb = -dst_stride_argb; 75 } 76#if defined(HAS_I422TOARGBROW_SSSE3) 77 if (TestCpuFlag(kCpuHasSSSE3)) { 78 I422ToARGBRow = I422ToARGBRow_Any_SSSE3; 79 if (IS_ALIGNED(width, 8)) { 80 I422ToARGBRow = I422ToARGBRow_SSSE3; 81 } 82 } 83#endif 84#if defined(HAS_I422TOARGBROW_AVX2) 85 if (TestCpuFlag(kCpuHasAVX2)) { 86 I422ToARGBRow = I422ToARGBRow_Any_AVX2; 87 if (IS_ALIGNED(width, 16)) { 88 I422ToARGBRow = I422ToARGBRow_AVX2; 89 } 90 } 91#endif 92#if defined(HAS_I422TOARGBROW_NEON) 93 if (TestCpuFlag(kCpuHasNEON)) { 94 I422ToARGBRow = I422ToARGBRow_Any_NEON; 95 if (IS_ALIGNED(width, 8)) { 96 I422ToARGBRow = I422ToARGBRow_NEON; 97 } 98 } 99#endif 100#if defined(HAS_I422TOARGBROW_DSPR2) 101 if (TestCpuFlag(kCpuHasDSPR2) && IS_ALIGNED(width, 4) && 102 IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) && 103 IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) && 104 IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) && 105 IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) { 106 I422ToARGBRow = I422ToARGBRow_DSPR2; 107 } 108#endif 109#if defined(HAS_I422TOARGBROW_MSA) 110 if (TestCpuFlag(kCpuHasMSA)) { 111 I422ToARGBRow = I422ToARGBRow_Any_MSA; 112 if (IS_ALIGNED(width, 8)) { 113 I422ToARGBRow = I422ToARGBRow_MSA; 114 } 115 } 116#endif 117 118 for (y = 0; y < height; ++y) { 119 I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width); 120 dst_argb += dst_stride_argb; 121 src_y += src_stride_y; 122 if (y & 1) { 123 src_u += src_stride_u; 124 src_v += src_stride_v; 125 } 126 } 127 return 0; 128} 129 130// Convert I420 to ARGB. 131LIBYUV_API 132int I420ToARGB(const uint8* src_y, 133 int src_stride_y, 134 const uint8* src_u, 135 int src_stride_u, 136 const uint8* src_v, 137 int src_stride_v, 138 uint8* dst_argb, 139 int dst_stride_argb, 140 int width, 141 int height) { 142 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v, 143 src_stride_v, dst_argb, dst_stride_argb, 144 &kYuvI601Constants, width, height); 145} 146 147// Convert I420 to ABGR. 148LIBYUV_API 149int I420ToABGR(const uint8* src_y, 150 int src_stride_y, 151 const uint8* src_u, 152 int src_stride_u, 153 const uint8* src_v, 154 int src_stride_v, 155 uint8* dst_abgr, 156 int dst_stride_abgr, 157 int width, 158 int height) { 159 return I420ToARGBMatrix(src_y, src_stride_y, src_v, 160 src_stride_v, // Swap U and V 161 src_u, src_stride_u, dst_abgr, dst_stride_abgr, 162 &kYvuI601Constants, // Use Yvu matrix 163 width, height); 164} 165 166// Convert J420 to ARGB. 167LIBYUV_API 168int J420ToARGB(const uint8* src_y, 169 int src_stride_y, 170 const uint8* src_u, 171 int src_stride_u, 172 const uint8* src_v, 173 int src_stride_v, 174 uint8* dst_argb, 175 int dst_stride_argb, 176 int width, 177 int height) { 178 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v, 179 src_stride_v, dst_argb, dst_stride_argb, 180 &kYuvJPEGConstants, width, height); 181} 182 183// Convert J420 to ABGR. 184LIBYUV_API 185int J420ToABGR(const uint8* src_y, 186 int src_stride_y, 187 const uint8* src_u, 188 int src_stride_u, 189 const uint8* src_v, 190 int src_stride_v, 191 uint8* dst_abgr, 192 int dst_stride_abgr, 193 int width, 194 int height) { 195 return I420ToARGBMatrix(src_y, src_stride_y, src_v, 196 src_stride_v, // Swap U and V 197 src_u, src_stride_u, dst_abgr, dst_stride_abgr, 198 &kYvuJPEGConstants, // Use Yvu matrix 199 width, height); 200} 201 202// Convert H420 to ARGB. 203LIBYUV_API 204int H420ToARGB(const uint8* src_y, 205 int src_stride_y, 206 const uint8* src_u, 207 int src_stride_u, 208 const uint8* src_v, 209 int src_stride_v, 210 uint8* dst_argb, 211 int dst_stride_argb, 212 int width, 213 int height) { 214 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v, 215 src_stride_v, dst_argb, dst_stride_argb, 216 &kYuvH709Constants, width, height); 217} 218 219// Convert H420 to ABGR. 220LIBYUV_API 221int H420ToABGR(const uint8* src_y, 222 int src_stride_y, 223 const uint8* src_u, 224 int src_stride_u, 225 const uint8* src_v, 226 int src_stride_v, 227 uint8* dst_abgr, 228 int dst_stride_abgr, 229 int width, 230 int height) { 231 return I420ToARGBMatrix(src_y, src_stride_y, src_v, 232 src_stride_v, // Swap U and V 233 src_u, src_stride_u, dst_abgr, dst_stride_abgr, 234 &kYvuH709Constants, // Use Yvu matrix 235 width, height); 236} 237 238// Convert I422 to ARGB with matrix 239static int I422ToARGBMatrix(const uint8* src_y, 240 int src_stride_y, 241 const uint8* src_u, 242 int src_stride_u, 243 const uint8* src_v, 244 int src_stride_v, 245 uint8* dst_argb, 246 int dst_stride_argb, 247 const struct YuvConstants* yuvconstants, 248 int width, 249 int height) { 250 int y; 251 void (*I422ToARGBRow)(const uint8* y_buf, const uint8* u_buf, 252 const uint8* v_buf, uint8* rgb_buf, 253 const struct YuvConstants* yuvconstants, int width) = 254 I422ToARGBRow_C; 255 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) { 256 return -1; 257 } 258 // Negative height means invert the image. 259 if (height < 0) { 260 height = -height; 261 dst_argb = dst_argb + (height - 1) * dst_stride_argb; 262 dst_stride_argb = -dst_stride_argb; 263 } 264 // Coalesce rows. 265 if (src_stride_y == width && src_stride_u * 2 == width && 266 src_stride_v * 2 == width && dst_stride_argb == width * 4) { 267 width *= height; 268 height = 1; 269 src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0; 270 } 271#if defined(HAS_I422TOARGBROW_SSSE3) 272 if (TestCpuFlag(kCpuHasSSSE3)) { 273 I422ToARGBRow = I422ToARGBRow_Any_SSSE3; 274 if (IS_ALIGNED(width, 8)) { 275 I422ToARGBRow = I422ToARGBRow_SSSE3; 276 } 277 } 278#endif 279#if defined(HAS_I422TOARGBROW_AVX2) 280 if (TestCpuFlag(kCpuHasAVX2)) { 281 I422ToARGBRow = I422ToARGBRow_Any_AVX2; 282 if (IS_ALIGNED(width, 16)) { 283 I422ToARGBRow = I422ToARGBRow_AVX2; 284 } 285 } 286#endif 287#if defined(HAS_I422TOARGBROW_NEON) 288 if (TestCpuFlag(kCpuHasNEON)) { 289 I422ToARGBRow = I422ToARGBRow_Any_NEON; 290 if (IS_ALIGNED(width, 8)) { 291 I422ToARGBRow = I422ToARGBRow_NEON; 292 } 293 } 294#endif 295#if defined(HAS_I422TOARGBROW_DSPR2) 296 if (TestCpuFlag(kCpuHasDSPR2) && IS_ALIGNED(width, 4) && 297 IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) && 298 IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) && 299 IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) && 300 IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) { 301 I422ToARGBRow = I422ToARGBRow_DSPR2; 302 } 303#endif 304#if defined(HAS_I422TOARGBROW_MSA) 305 if (TestCpuFlag(kCpuHasMSA)) { 306 I422ToARGBRow = I422ToARGBRow_Any_MSA; 307 if (IS_ALIGNED(width, 8)) { 308 I422ToARGBRow = I422ToARGBRow_MSA; 309 } 310 } 311#endif 312 313 for (y = 0; y < height; ++y) { 314 I422ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width); 315 dst_argb += dst_stride_argb; 316 src_y += src_stride_y; 317 src_u += src_stride_u; 318 src_v += src_stride_v; 319 } 320 return 0; 321} 322 323// Convert I422 to ARGB. 324LIBYUV_API 325int I422ToARGB(const uint8* src_y, 326 int src_stride_y, 327 const uint8* src_u, 328 int src_stride_u, 329 const uint8* src_v, 330 int src_stride_v, 331 uint8* dst_argb, 332 int dst_stride_argb, 333 int width, 334 int height) { 335 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v, 336 src_stride_v, dst_argb, dst_stride_argb, 337 &kYuvI601Constants, width, height); 338} 339 340// Convert I422 to ABGR. 341LIBYUV_API 342int I422ToABGR(const uint8* src_y, 343 int src_stride_y, 344 const uint8* src_u, 345 int src_stride_u, 346 const uint8* src_v, 347 int src_stride_v, 348 uint8* dst_abgr, 349 int dst_stride_abgr, 350 int width, 351 int height) { 352 return I422ToARGBMatrix(src_y, src_stride_y, src_v, 353 src_stride_v, // Swap U and V 354 src_u, src_stride_u, dst_abgr, dst_stride_abgr, 355 &kYvuI601Constants, // Use Yvu matrix 356 width, height); 357} 358 359// Convert J422 to ARGB. 360LIBYUV_API 361int J422ToARGB(const uint8* src_y, 362 int src_stride_y, 363 const uint8* src_u, 364 int src_stride_u, 365 const uint8* src_v, 366 int src_stride_v, 367 uint8* dst_argb, 368 int dst_stride_argb, 369 int width, 370 int height) { 371 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v, 372 src_stride_v, dst_argb, dst_stride_argb, 373 &kYuvJPEGConstants, width, height); 374} 375 376// Convert J422 to ABGR. 377LIBYUV_API 378int J422ToABGR(const uint8* src_y, 379 int src_stride_y, 380 const uint8* src_u, 381 int src_stride_u, 382 const uint8* src_v, 383 int src_stride_v, 384 uint8* dst_abgr, 385 int dst_stride_abgr, 386 int width, 387 int height) { 388 return I422ToARGBMatrix(src_y, src_stride_y, src_v, 389 src_stride_v, // Swap U and V 390 src_u, src_stride_u, dst_abgr, dst_stride_abgr, 391 &kYvuJPEGConstants, // Use Yvu matrix 392 width, height); 393} 394 395// Convert H422 to ARGB. 396LIBYUV_API 397int H422ToARGB(const uint8* src_y, 398 int src_stride_y, 399 const uint8* src_u, 400 int src_stride_u, 401 const uint8* src_v, 402 int src_stride_v, 403 uint8* dst_argb, 404 int dst_stride_argb, 405 int width, 406 int height) { 407 return I422ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v, 408 src_stride_v, dst_argb, dst_stride_argb, 409 &kYuvH709Constants, width, height); 410} 411 412// Convert H422 to ABGR. 413LIBYUV_API 414int H422ToABGR(const uint8* src_y, 415 int src_stride_y, 416 const uint8* src_u, 417 int src_stride_u, 418 const uint8* src_v, 419 int src_stride_v, 420 uint8* dst_abgr, 421 int dst_stride_abgr, 422 int width, 423 int height) { 424 return I422ToARGBMatrix(src_y, src_stride_y, src_v, 425 src_stride_v, // Swap U and V 426 src_u, src_stride_u, dst_abgr, dst_stride_abgr, 427 &kYvuH709Constants, // Use Yvu matrix 428 width, height); 429} 430 431// Convert I444 to ARGB with matrix 432static int I444ToARGBMatrix(const uint8* src_y, 433 int src_stride_y, 434 const uint8* src_u, 435 int src_stride_u, 436 const uint8* src_v, 437 int src_stride_v, 438 uint8* dst_argb, 439 int dst_stride_argb, 440 const struct YuvConstants* yuvconstants, 441 int width, 442 int height) { 443 int y; 444 void (*I444ToARGBRow)(const uint8* y_buf, const uint8* u_buf, 445 const uint8* v_buf, uint8* rgb_buf, 446 const struct YuvConstants* yuvconstants, int width) = 447 I444ToARGBRow_C; 448 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) { 449 return -1; 450 } 451 // Negative height means invert the image. 452 if (height < 0) { 453 height = -height; 454 dst_argb = dst_argb + (height - 1) * dst_stride_argb; 455 dst_stride_argb = -dst_stride_argb; 456 } 457 // Coalesce rows. 458 if (src_stride_y == width && src_stride_u == width && src_stride_v == width && 459 dst_stride_argb == width * 4) { 460 width *= height; 461 height = 1; 462 src_stride_y = src_stride_u = src_stride_v = dst_stride_argb = 0; 463 } 464#if defined(HAS_I444TOARGBROW_SSSE3) 465 if (TestCpuFlag(kCpuHasSSSE3)) { 466 I444ToARGBRow = I444ToARGBRow_Any_SSSE3; 467 if (IS_ALIGNED(width, 8)) { 468 I444ToARGBRow = I444ToARGBRow_SSSE3; 469 } 470 } 471#endif 472#if defined(HAS_I444TOARGBROW_AVX2) 473 if (TestCpuFlag(kCpuHasAVX2)) { 474 I444ToARGBRow = I444ToARGBRow_Any_AVX2; 475 if (IS_ALIGNED(width, 16)) { 476 I444ToARGBRow = I444ToARGBRow_AVX2; 477 } 478 } 479#endif 480#if defined(HAS_I444TOARGBROW_NEON) 481 if (TestCpuFlag(kCpuHasNEON)) { 482 I444ToARGBRow = I444ToARGBRow_Any_NEON; 483 if (IS_ALIGNED(width, 8)) { 484 I444ToARGBRow = I444ToARGBRow_NEON; 485 } 486 } 487#endif 488#if defined(HAS_I444TOARGBROW_DSPR2) 489 if (TestCpuFlag(kCpuHasDSPR2)) { 490 I444ToARGBRow = I444ToARGBRow_Any_DSPR2; 491 if (IS_ALIGNED(width, 8)) { 492 I444ToARGBRow = I444ToARGBRow_DSPR2; 493 } 494 } 495#endif 496#if defined(HAS_I444TOARGBROW_MSA) 497 if (TestCpuFlag(kCpuHasMSA)) { 498 I444ToARGBRow = I444ToARGBRow_Any_MSA; 499 if (IS_ALIGNED(width, 8)) { 500 I444ToARGBRow = I444ToARGBRow_MSA; 501 } 502 } 503#endif 504 505 for (y = 0; y < height; ++y) { 506 I444ToARGBRow(src_y, src_u, src_v, dst_argb, yuvconstants, width); 507 dst_argb += dst_stride_argb; 508 src_y += src_stride_y; 509 src_u += src_stride_u; 510 src_v += src_stride_v; 511 } 512 return 0; 513} 514 515// Convert I444 to ARGB. 516LIBYUV_API 517int I444ToARGB(const uint8* src_y, 518 int src_stride_y, 519 const uint8* src_u, 520 int src_stride_u, 521 const uint8* src_v, 522 int src_stride_v, 523 uint8* dst_argb, 524 int dst_stride_argb, 525 int width, 526 int height) { 527 return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v, 528 src_stride_v, dst_argb, dst_stride_argb, 529 &kYuvI601Constants, width, height); 530} 531 532// Convert I444 to ABGR. 533LIBYUV_API 534int I444ToABGR(const uint8* src_y, 535 int src_stride_y, 536 const uint8* src_u, 537 int src_stride_u, 538 const uint8* src_v, 539 int src_stride_v, 540 uint8* dst_abgr, 541 int dst_stride_abgr, 542 int width, 543 int height) { 544 return I444ToARGBMatrix(src_y, src_stride_y, src_v, 545 src_stride_v, // Swap U and V 546 src_u, src_stride_u, dst_abgr, dst_stride_abgr, 547 &kYvuI601Constants, // Use Yvu matrix 548 width, height); 549} 550 551// Convert J444 to ARGB. 552LIBYUV_API 553int J444ToARGB(const uint8* src_y, 554 int src_stride_y, 555 const uint8* src_u, 556 int src_stride_u, 557 const uint8* src_v, 558 int src_stride_v, 559 uint8* dst_argb, 560 int dst_stride_argb, 561 int width, 562 int height) { 563 return I444ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v, 564 src_stride_v, dst_argb, dst_stride_argb, 565 &kYuvJPEGConstants, width, height); 566} 567 568// Convert I420 with Alpha to preattenuated ARGB. 569static int I420AlphaToARGBMatrix(const uint8* src_y, 570 int src_stride_y, 571 const uint8* src_u, 572 int src_stride_u, 573 const uint8* src_v, 574 int src_stride_v, 575 const uint8* src_a, 576 int src_stride_a, 577 uint8* dst_argb, 578 int dst_stride_argb, 579 const struct YuvConstants* yuvconstants, 580 int width, 581 int height, 582 int attenuate) { 583 int y; 584 void (*I422AlphaToARGBRow)(const uint8* y_buf, const uint8* u_buf, 585 const uint8* v_buf, const uint8* a_buf, 586 uint8* dst_argb, 587 const struct YuvConstants* yuvconstants, 588 int width) = I422AlphaToARGBRow_C; 589 void (*ARGBAttenuateRow)(const uint8* src_argb, uint8* dst_argb, int width) = 590 ARGBAttenuateRow_C; 591 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) { 592 return -1; 593 } 594 // Negative height means invert the image. 595 if (height < 0) { 596 height = -height; 597 dst_argb = dst_argb + (height - 1) * dst_stride_argb; 598 dst_stride_argb = -dst_stride_argb; 599 } 600#if defined(HAS_I422ALPHATOARGBROW_SSSE3) 601 if (TestCpuFlag(kCpuHasSSSE3)) { 602 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_SSSE3; 603 if (IS_ALIGNED(width, 8)) { 604 I422AlphaToARGBRow = I422AlphaToARGBRow_SSSE3; 605 } 606 } 607#endif 608#if defined(HAS_I422ALPHATOARGBROW_AVX2) 609 if (TestCpuFlag(kCpuHasAVX2)) { 610 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_AVX2; 611 if (IS_ALIGNED(width, 16)) { 612 I422AlphaToARGBRow = I422AlphaToARGBRow_AVX2; 613 } 614 } 615#endif 616#if defined(HAS_I422ALPHATOARGBROW_NEON) 617 if (TestCpuFlag(kCpuHasNEON)) { 618 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_NEON; 619 if (IS_ALIGNED(width, 8)) { 620 I422AlphaToARGBRow = I422AlphaToARGBRow_NEON; 621 } 622 } 623#endif 624#if defined(HAS_I422ALPHATOARGBROW_DSPR2) 625 if (TestCpuFlag(kCpuHasDSPR2) && IS_ALIGNED(width, 4) && 626 IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) && 627 IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) && 628 IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) && 629 IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) { 630 I422AlphaToARGBRow = I422AlphaToARGBRow_DSPR2; 631 } 632#endif 633#if defined(HAS_I422ALPHATOARGBROW_MSA) 634 if (TestCpuFlag(kCpuHasMSA)) { 635 I422AlphaToARGBRow = I422AlphaToARGBRow_Any_MSA; 636 if (IS_ALIGNED(width, 8)) { 637 I422AlphaToARGBRow = I422AlphaToARGBRow_MSA; 638 } 639 } 640#endif 641#if defined(HAS_ARGBATTENUATEROW_SSSE3) 642 if (TestCpuFlag(kCpuHasSSSE3)) { 643 ARGBAttenuateRow = ARGBAttenuateRow_Any_SSSE3; 644 if (IS_ALIGNED(width, 4)) { 645 ARGBAttenuateRow = ARGBAttenuateRow_SSSE3; 646 } 647 } 648#endif 649#if defined(HAS_ARGBATTENUATEROW_AVX2) 650 if (TestCpuFlag(kCpuHasAVX2)) { 651 ARGBAttenuateRow = ARGBAttenuateRow_Any_AVX2; 652 if (IS_ALIGNED(width, 8)) { 653 ARGBAttenuateRow = ARGBAttenuateRow_AVX2; 654 } 655 } 656#endif 657#if defined(HAS_ARGBATTENUATEROW_NEON) 658 if (TestCpuFlag(kCpuHasNEON)) { 659 ARGBAttenuateRow = ARGBAttenuateRow_Any_NEON; 660 if (IS_ALIGNED(width, 8)) { 661 ARGBAttenuateRow = ARGBAttenuateRow_NEON; 662 } 663 } 664#endif 665#if defined(HAS_ARGBATTENUATEROW_MSA) 666 if (TestCpuFlag(kCpuHasMSA)) { 667 ARGBAttenuateRow = ARGBAttenuateRow_Any_MSA; 668 if (IS_ALIGNED(width, 8)) { 669 ARGBAttenuateRow = ARGBAttenuateRow_MSA; 670 } 671 } 672#endif 673 674 for (y = 0; y < height; ++y) { 675 I422AlphaToARGBRow(src_y, src_u, src_v, src_a, dst_argb, yuvconstants, 676 width); 677 if (attenuate) { 678 ARGBAttenuateRow(dst_argb, dst_argb, width); 679 } 680 dst_argb += dst_stride_argb; 681 src_a += src_stride_a; 682 src_y += src_stride_y; 683 if (y & 1) { 684 src_u += src_stride_u; 685 src_v += src_stride_v; 686 } 687 } 688 return 0; 689} 690 691// Convert I420 with Alpha to ARGB. 692LIBYUV_API 693int I420AlphaToARGB(const uint8* src_y, 694 int src_stride_y, 695 const uint8* src_u, 696 int src_stride_u, 697 const uint8* src_v, 698 int src_stride_v, 699 const uint8* src_a, 700 int src_stride_a, 701 uint8* dst_argb, 702 int dst_stride_argb, 703 int width, 704 int height, 705 int attenuate) { 706 return I420AlphaToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v, 707 src_stride_v, src_a, src_stride_a, dst_argb, 708 dst_stride_argb, &kYuvI601Constants, width, 709 height, attenuate); 710} 711 712// Convert I420 with Alpha to ABGR. 713LIBYUV_API 714int I420AlphaToABGR(const uint8* src_y, 715 int src_stride_y, 716 const uint8* src_u, 717 int src_stride_u, 718 const uint8* src_v, 719 int src_stride_v, 720 const uint8* src_a, 721 int src_stride_a, 722 uint8* dst_abgr, 723 int dst_stride_abgr, 724 int width, 725 int height, 726 int attenuate) { 727 return I420AlphaToARGBMatrix( 728 src_y, src_stride_y, src_v, src_stride_v, // Swap U and V 729 src_u, src_stride_u, src_a, src_stride_a, dst_abgr, dst_stride_abgr, 730 &kYvuI601Constants, // Use Yvu matrix 731 width, height, attenuate); 732} 733 734// Convert I400 to ARGB. 735LIBYUV_API 736int I400ToARGB(const uint8* src_y, 737 int src_stride_y, 738 uint8* dst_argb, 739 int dst_stride_argb, 740 int width, 741 int height) { 742 int y; 743 void (*I400ToARGBRow)(const uint8* y_buf, uint8* rgb_buf, int width) = 744 I400ToARGBRow_C; 745 if (!src_y || !dst_argb || width <= 0 || height == 0) { 746 return -1; 747 } 748 // Negative height means invert the image. 749 if (height < 0) { 750 height = -height; 751 dst_argb = dst_argb + (height - 1) * dst_stride_argb; 752 dst_stride_argb = -dst_stride_argb; 753 } 754 // Coalesce rows. 755 if (src_stride_y == width && dst_stride_argb == width * 4) { 756 width *= height; 757 height = 1; 758 src_stride_y = dst_stride_argb = 0; 759 } 760#if defined(HAS_I400TOARGBROW_SSE2) 761 if (TestCpuFlag(kCpuHasSSE2)) { 762 I400ToARGBRow = I400ToARGBRow_Any_SSE2; 763 if (IS_ALIGNED(width, 8)) { 764 I400ToARGBRow = I400ToARGBRow_SSE2; 765 } 766 } 767#endif 768#if defined(HAS_I400TOARGBROW_AVX2) 769 if (TestCpuFlag(kCpuHasAVX2)) { 770 I400ToARGBRow = I400ToARGBRow_Any_AVX2; 771 if (IS_ALIGNED(width, 16)) { 772 I400ToARGBRow = I400ToARGBRow_AVX2; 773 } 774 } 775#endif 776#if defined(HAS_I400TOARGBROW_NEON) 777 if (TestCpuFlag(kCpuHasNEON)) { 778 I400ToARGBRow = I400ToARGBRow_Any_NEON; 779 if (IS_ALIGNED(width, 8)) { 780 I400ToARGBRow = I400ToARGBRow_NEON; 781 } 782 } 783#endif 784#if defined(HAS_I400TOARGBROW_MSA) 785 if (TestCpuFlag(kCpuHasMSA)) { 786 I400ToARGBRow = I400ToARGBRow_Any_MSA; 787 if (IS_ALIGNED(width, 16)) { 788 I400ToARGBRow = I400ToARGBRow_MSA; 789 } 790 } 791#endif 792 793 for (y = 0; y < height; ++y) { 794 I400ToARGBRow(src_y, dst_argb, width); 795 dst_argb += dst_stride_argb; 796 src_y += src_stride_y; 797 } 798 return 0; 799} 800 801// Convert J400 to ARGB. 802LIBYUV_API 803int J400ToARGB(const uint8* src_y, 804 int src_stride_y, 805 uint8* dst_argb, 806 int dst_stride_argb, 807 int width, 808 int height) { 809 int y; 810 void (*J400ToARGBRow)(const uint8* src_y, uint8* dst_argb, int width) = 811 J400ToARGBRow_C; 812 if (!src_y || !dst_argb || width <= 0 || height == 0) { 813 return -1; 814 } 815 // Negative height means invert the image. 816 if (height < 0) { 817 height = -height; 818 src_y = src_y + (height - 1) * src_stride_y; 819 src_stride_y = -src_stride_y; 820 } 821 // Coalesce rows. 822 if (src_stride_y == width && dst_stride_argb == width * 4) { 823 width *= height; 824 height = 1; 825 src_stride_y = dst_stride_argb = 0; 826 } 827#if defined(HAS_J400TOARGBROW_SSE2) 828 if (TestCpuFlag(kCpuHasSSE2)) { 829 J400ToARGBRow = J400ToARGBRow_Any_SSE2; 830 if (IS_ALIGNED(width, 8)) { 831 J400ToARGBRow = J400ToARGBRow_SSE2; 832 } 833 } 834#endif 835#if defined(HAS_J400TOARGBROW_AVX2) 836 if (TestCpuFlag(kCpuHasAVX2)) { 837 J400ToARGBRow = J400ToARGBRow_Any_AVX2; 838 if (IS_ALIGNED(width, 16)) { 839 J400ToARGBRow = J400ToARGBRow_AVX2; 840 } 841 } 842#endif 843#if defined(HAS_J400TOARGBROW_NEON) 844 if (TestCpuFlag(kCpuHasNEON)) { 845 J400ToARGBRow = J400ToARGBRow_Any_NEON; 846 if (IS_ALIGNED(width, 8)) { 847 J400ToARGBRow = J400ToARGBRow_NEON; 848 } 849 } 850#endif 851#if defined(HAS_J400TOARGBROW_MSA) 852 if (TestCpuFlag(kCpuHasMSA)) { 853 J400ToARGBRow = J400ToARGBRow_Any_MSA; 854 if (IS_ALIGNED(width, 16)) { 855 J400ToARGBRow = J400ToARGBRow_MSA; 856 } 857 } 858#endif 859 for (y = 0; y < height; ++y) { 860 J400ToARGBRow(src_y, dst_argb, width); 861 src_y += src_stride_y; 862 dst_argb += dst_stride_argb; 863 } 864 return 0; 865} 866 867// Shuffle table for converting BGRA to ARGB. 868static uvec8 kShuffleMaskBGRAToARGB = {3u, 2u, 1u, 0u, 7u, 6u, 5u, 4u, 869 11u, 10u, 9u, 8u, 15u, 14u, 13u, 12u}; 870 871// Shuffle table for converting ABGR to ARGB. 872static uvec8 kShuffleMaskABGRToARGB = {2u, 1u, 0u, 3u, 6u, 5u, 4u, 7u, 873 10u, 9u, 8u, 11u, 14u, 13u, 12u, 15u}; 874 875// Shuffle table for converting RGBA to ARGB. 876static uvec8 kShuffleMaskRGBAToARGB = {1u, 2u, 3u, 0u, 5u, 6u, 7u, 4u, 877 9u, 10u, 11u, 8u, 13u, 14u, 15u, 12u}; 878 879// Convert BGRA to ARGB. 880LIBYUV_API 881int BGRAToARGB(const uint8* src_bgra, 882 int src_stride_bgra, 883 uint8* dst_argb, 884 int dst_stride_argb, 885 int width, 886 int height) { 887 return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb, 888 (const uint8*)(&kShuffleMaskBGRAToARGB), width, height); 889} 890 891// Convert ARGB to BGRA (same as BGRAToARGB). 892LIBYUV_API 893int ARGBToBGRA(const uint8* src_bgra, 894 int src_stride_bgra, 895 uint8* dst_argb, 896 int dst_stride_argb, 897 int width, 898 int height) { 899 return ARGBShuffle(src_bgra, src_stride_bgra, dst_argb, dst_stride_argb, 900 (const uint8*)(&kShuffleMaskBGRAToARGB), width, height); 901} 902 903// Convert ABGR to ARGB. 904LIBYUV_API 905int ABGRToARGB(const uint8* src_abgr, 906 int src_stride_abgr, 907 uint8* dst_argb, 908 int dst_stride_argb, 909 int width, 910 int height) { 911 return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb, 912 (const uint8*)(&kShuffleMaskABGRToARGB), width, height); 913} 914 915// Convert ARGB to ABGR to (same as ABGRToARGB). 916LIBYUV_API 917int ARGBToABGR(const uint8* src_abgr, 918 int src_stride_abgr, 919 uint8* dst_argb, 920 int dst_stride_argb, 921 int width, 922 int height) { 923 return ARGBShuffle(src_abgr, src_stride_abgr, dst_argb, dst_stride_argb, 924 (const uint8*)(&kShuffleMaskABGRToARGB), width, height); 925} 926 927// Convert RGBA to ARGB. 928LIBYUV_API 929int RGBAToARGB(const uint8* src_rgba, 930 int src_stride_rgba, 931 uint8* dst_argb, 932 int dst_stride_argb, 933 int width, 934 int height) { 935 return ARGBShuffle(src_rgba, src_stride_rgba, dst_argb, dst_stride_argb, 936 (const uint8*)(&kShuffleMaskRGBAToARGB), width, height); 937} 938 939// Convert RGB24 to ARGB. 940LIBYUV_API 941int RGB24ToARGB(const uint8* src_rgb24, 942 int src_stride_rgb24, 943 uint8* dst_argb, 944 int dst_stride_argb, 945 int width, 946 int height) { 947 int y; 948 void (*RGB24ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int width) = 949 RGB24ToARGBRow_C; 950 if (!src_rgb24 || !dst_argb || width <= 0 || height == 0) { 951 return -1; 952 } 953 // Negative height means invert the image. 954 if (height < 0) { 955 height = -height; 956 src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24; 957 src_stride_rgb24 = -src_stride_rgb24; 958 } 959 // Coalesce rows. 960 if (src_stride_rgb24 == width * 3 && dst_stride_argb == width * 4) { 961 width *= height; 962 height = 1; 963 src_stride_rgb24 = dst_stride_argb = 0; 964 } 965#if defined(HAS_RGB24TOARGBROW_SSSE3) 966 if (TestCpuFlag(kCpuHasSSSE3)) { 967 RGB24ToARGBRow = RGB24ToARGBRow_Any_SSSE3; 968 if (IS_ALIGNED(width, 16)) { 969 RGB24ToARGBRow = RGB24ToARGBRow_SSSE3; 970 } 971 } 972#endif 973#if defined(HAS_RGB24TOARGBROW_NEON) 974 if (TestCpuFlag(kCpuHasNEON)) { 975 RGB24ToARGBRow = RGB24ToARGBRow_Any_NEON; 976 if (IS_ALIGNED(width, 8)) { 977 RGB24ToARGBRow = RGB24ToARGBRow_NEON; 978 } 979 } 980#endif 981#if defined(HAS_RGB24TOARGBROW_DSPR2) 982 if (TestCpuFlag(kCpuHasDSPR2)) { 983 RGB24ToARGBRow = RGB24ToARGBRow_Any_DSPR2; 984 if (IS_ALIGNED(width, 8)) { 985 RGB24ToARGBRow = RGB24ToARGBRow_DSPR2; 986 } 987 } 988#endif 989#if defined(HAS_RGB24TOARGBROW_MSA) 990 if (TestCpuFlag(kCpuHasMSA)) { 991 RGB24ToARGBRow = RGB24ToARGBRow_Any_MSA; 992 if (IS_ALIGNED(width, 16)) { 993 RGB24ToARGBRow = RGB24ToARGBRow_MSA; 994 } 995 } 996#endif 997 998 for (y = 0; y < height; ++y) { 999 RGB24ToARGBRow(src_rgb24, dst_argb, width); 1000 src_rgb24 += src_stride_rgb24; 1001 dst_argb += dst_stride_argb; 1002 } 1003 return 0; 1004} 1005 1006// Convert RAW to ARGB. 1007LIBYUV_API 1008int RAWToARGB(const uint8* src_raw, 1009 int src_stride_raw, 1010 uint8* dst_argb, 1011 int dst_stride_argb, 1012 int width, 1013 int height) { 1014 int y; 1015 void (*RAWToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int width) = 1016 RAWToARGBRow_C; 1017 if (!src_raw || !dst_argb || width <= 0 || height == 0) { 1018 return -1; 1019 } 1020 // Negative height means invert the image. 1021 if (height < 0) { 1022 height = -height; 1023 src_raw = src_raw + (height - 1) * src_stride_raw; 1024 src_stride_raw = -src_stride_raw; 1025 } 1026 // Coalesce rows. 1027 if (src_stride_raw == width * 3 && dst_stride_argb == width * 4) { 1028 width *= height; 1029 height = 1; 1030 src_stride_raw = dst_stride_argb = 0; 1031 } 1032#if defined(HAS_RAWTOARGBROW_SSSE3) 1033 if (TestCpuFlag(kCpuHasSSSE3)) { 1034 RAWToARGBRow = RAWToARGBRow_Any_SSSE3; 1035 if (IS_ALIGNED(width, 16)) { 1036 RAWToARGBRow = RAWToARGBRow_SSSE3; 1037 } 1038 } 1039#endif 1040#if defined(HAS_RAWTOARGBROW_NEON) 1041 if (TestCpuFlag(kCpuHasNEON)) { 1042 RAWToARGBRow = RAWToARGBRow_Any_NEON; 1043 if (IS_ALIGNED(width, 8)) { 1044 RAWToARGBRow = RAWToARGBRow_NEON; 1045 } 1046 } 1047#endif 1048#if defined(HAS_RAWTOARGBROW_DSPR2) 1049 if (TestCpuFlag(kCpuHasDSPR2)) { 1050 RAWToARGBRow = RAWToARGBRow_Any_DSPR2; 1051 if (IS_ALIGNED(width, 8)) { 1052 RAWToARGBRow = RAWToARGBRow_DSPR2; 1053 } 1054 } 1055#endif 1056#if defined(HAS_RAWTOARGBROW_MSA) 1057 if (TestCpuFlag(kCpuHasMSA)) { 1058 RAWToARGBRow = RAWToARGBRow_Any_MSA; 1059 if (IS_ALIGNED(width, 16)) { 1060 RAWToARGBRow = RAWToARGBRow_MSA; 1061 } 1062 } 1063#endif 1064 1065 for (y = 0; y < height; ++y) { 1066 RAWToARGBRow(src_raw, dst_argb, width); 1067 src_raw += src_stride_raw; 1068 dst_argb += dst_stride_argb; 1069 } 1070 return 0; 1071} 1072 1073// Convert RGB565 to ARGB. 1074LIBYUV_API 1075int RGB565ToARGB(const uint8* src_rgb565, 1076 int src_stride_rgb565, 1077 uint8* dst_argb, 1078 int dst_stride_argb, 1079 int width, 1080 int height) { 1081 int y; 1082 void (*RGB565ToARGBRow)(const uint8* src_rgb565, uint8* dst_argb, int width) = 1083 RGB565ToARGBRow_C; 1084 if (!src_rgb565 || !dst_argb || width <= 0 || height == 0) { 1085 return -1; 1086 } 1087 // Negative height means invert the image. 1088 if (height < 0) { 1089 height = -height; 1090 src_rgb565 = src_rgb565 + (height - 1) * src_stride_rgb565; 1091 src_stride_rgb565 = -src_stride_rgb565; 1092 } 1093 // Coalesce rows. 1094 if (src_stride_rgb565 == width * 2 && dst_stride_argb == width * 4) { 1095 width *= height; 1096 height = 1; 1097 src_stride_rgb565 = dst_stride_argb = 0; 1098 } 1099#if defined(HAS_RGB565TOARGBROW_SSE2) 1100 if (TestCpuFlag(kCpuHasSSE2)) { 1101 RGB565ToARGBRow = RGB565ToARGBRow_Any_SSE2; 1102 if (IS_ALIGNED(width, 8)) { 1103 RGB565ToARGBRow = RGB565ToARGBRow_SSE2; 1104 } 1105 } 1106#endif 1107#if defined(HAS_RGB565TOARGBROW_AVX2) 1108 if (TestCpuFlag(kCpuHasAVX2)) { 1109 RGB565ToARGBRow = RGB565ToARGBRow_Any_AVX2; 1110 if (IS_ALIGNED(width, 16)) { 1111 RGB565ToARGBRow = RGB565ToARGBRow_AVX2; 1112 } 1113 } 1114#endif 1115#if defined(HAS_RGB565TOARGBROW_NEON) 1116 if (TestCpuFlag(kCpuHasNEON)) { 1117 RGB565ToARGBRow = RGB565ToARGBRow_Any_NEON; 1118 if (IS_ALIGNED(width, 8)) { 1119 RGB565ToARGBRow = RGB565ToARGBRow_NEON; 1120 } 1121 } 1122#endif 1123#if defined(HAS_RGB565TOARGBROW_DSPR2) 1124 if (TestCpuFlag(kCpuHasDSPR2)) { 1125 RGB565ToARGBRow = RGB565ToARGBRow_Any_DSPR2; 1126 if (IS_ALIGNED(width, 8)) { 1127 RGB565ToARGBRow = RGB565ToARGBRow_DSPR2; 1128 } 1129 } 1130#endif 1131#if defined(HAS_RGB565TOARGBROW_MSA) 1132 if (TestCpuFlag(kCpuHasMSA)) { 1133 RGB565ToARGBRow = RGB565ToARGBRow_Any_MSA; 1134 if (IS_ALIGNED(width, 16)) { 1135 RGB565ToARGBRow = RGB565ToARGBRow_MSA; 1136 } 1137 } 1138#endif 1139 1140 for (y = 0; y < height; ++y) { 1141 RGB565ToARGBRow(src_rgb565, dst_argb, width); 1142 src_rgb565 += src_stride_rgb565; 1143 dst_argb += dst_stride_argb; 1144 } 1145 return 0; 1146} 1147 1148// Convert ARGB1555 to ARGB. 1149LIBYUV_API 1150int ARGB1555ToARGB(const uint8* src_argb1555, 1151 int src_stride_argb1555, 1152 uint8* dst_argb, 1153 int dst_stride_argb, 1154 int width, 1155 int height) { 1156 int y; 1157 void (*ARGB1555ToARGBRow)(const uint8* src_argb1555, uint8* dst_argb, 1158 int width) = ARGB1555ToARGBRow_C; 1159 if (!src_argb1555 || !dst_argb || width <= 0 || height == 0) { 1160 return -1; 1161 } 1162 // Negative height means invert the image. 1163 if (height < 0) { 1164 height = -height; 1165 src_argb1555 = src_argb1555 + (height - 1) * src_stride_argb1555; 1166 src_stride_argb1555 = -src_stride_argb1555; 1167 } 1168 // Coalesce rows. 1169 if (src_stride_argb1555 == width * 2 && dst_stride_argb == width * 4) { 1170 width *= height; 1171 height = 1; 1172 src_stride_argb1555 = dst_stride_argb = 0; 1173 } 1174#if defined(HAS_ARGB1555TOARGBROW_SSE2) 1175 if (TestCpuFlag(kCpuHasSSE2)) { 1176 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_SSE2; 1177 if (IS_ALIGNED(width, 8)) { 1178 ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2; 1179 } 1180 } 1181#endif 1182#if defined(HAS_ARGB1555TOARGBROW_AVX2) 1183 if (TestCpuFlag(kCpuHasAVX2)) { 1184 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_AVX2; 1185 if (IS_ALIGNED(width, 16)) { 1186 ARGB1555ToARGBRow = ARGB1555ToARGBRow_AVX2; 1187 } 1188 } 1189#endif 1190#if defined(HAS_ARGB1555TOARGBROW_NEON) 1191 if (TestCpuFlag(kCpuHasNEON)) { 1192 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_NEON; 1193 if (IS_ALIGNED(width, 8)) { 1194 ARGB1555ToARGBRow = ARGB1555ToARGBRow_NEON; 1195 } 1196 } 1197#endif 1198#if defined(HAS_ARGB1555TOARGBROW_DSPR2) 1199 if (TestCpuFlag(kCpuHasDSPR2)) { 1200 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_DSPR2; 1201 if (IS_ALIGNED(width, 4)) { 1202 ARGB1555ToARGBRow = ARGB1555ToARGBRow_DSPR2; 1203 } 1204 } 1205#endif 1206#if defined(HAS_ARGB1555TOARGBROW_MSA) 1207 if (TestCpuFlag(kCpuHasMSA)) { 1208 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_MSA; 1209 if (IS_ALIGNED(width, 16)) { 1210 ARGB1555ToARGBRow = ARGB1555ToARGBRow_MSA; 1211 } 1212 } 1213#endif 1214 1215 for (y = 0; y < height; ++y) { 1216 ARGB1555ToARGBRow(src_argb1555, dst_argb, width); 1217 src_argb1555 += src_stride_argb1555; 1218 dst_argb += dst_stride_argb; 1219 } 1220 return 0; 1221} 1222 1223// Convert ARGB4444 to ARGB. 1224LIBYUV_API 1225int ARGB4444ToARGB(const uint8* src_argb4444, 1226 int src_stride_argb4444, 1227 uint8* dst_argb, 1228 int dst_stride_argb, 1229 int width, 1230 int height) { 1231 int y; 1232 void (*ARGB4444ToARGBRow)(const uint8* src_argb4444, uint8* dst_argb, 1233 int width) = ARGB4444ToARGBRow_C; 1234 if (!src_argb4444 || !dst_argb || width <= 0 || height == 0) { 1235 return -1; 1236 } 1237 // Negative height means invert the image. 1238 if (height < 0) { 1239 height = -height; 1240 src_argb4444 = src_argb4444 + (height - 1) * src_stride_argb4444; 1241 src_stride_argb4444 = -src_stride_argb4444; 1242 } 1243 // Coalesce rows. 1244 if (src_stride_argb4444 == width * 2 && dst_stride_argb == width * 4) { 1245 width *= height; 1246 height = 1; 1247 src_stride_argb4444 = dst_stride_argb = 0; 1248 } 1249#if defined(HAS_ARGB4444TOARGBROW_SSE2) 1250 if (TestCpuFlag(kCpuHasSSE2)) { 1251 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_SSE2; 1252 if (IS_ALIGNED(width, 8)) { 1253 ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2; 1254 } 1255 } 1256#endif 1257#if defined(HAS_ARGB4444TOARGBROW_AVX2) 1258 if (TestCpuFlag(kCpuHasAVX2)) { 1259 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_AVX2; 1260 if (IS_ALIGNED(width, 16)) { 1261 ARGB4444ToARGBRow = ARGB4444ToARGBRow_AVX2; 1262 } 1263 } 1264#endif 1265#if defined(HAS_ARGB4444TOARGBROW_NEON) 1266 if (TestCpuFlag(kCpuHasNEON)) { 1267 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_NEON; 1268 if (IS_ALIGNED(width, 8)) { 1269 ARGB4444ToARGBRow = ARGB4444ToARGBRow_NEON; 1270 } 1271 } 1272#endif 1273#if defined(HAS_ARGB4444TOARGBROW_DSPR2) 1274 if (TestCpuFlag(kCpuHasDSPR2)) { 1275 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_DSPR2; 1276 if (IS_ALIGNED(width, 4)) { 1277 ARGB4444ToARGBRow = ARGB4444ToARGBRow_DSPR2; 1278 } 1279 } 1280#endif 1281#if defined(HAS_ARGB4444TOARGBROW_MSA) 1282 if (TestCpuFlag(kCpuHasMSA)) { 1283 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_MSA; 1284 if (IS_ALIGNED(width, 16)) { 1285 ARGB4444ToARGBRow = ARGB4444ToARGBRow_MSA; 1286 } 1287 } 1288#endif 1289 1290 for (y = 0; y < height; ++y) { 1291 ARGB4444ToARGBRow(src_argb4444, dst_argb, width); 1292 src_argb4444 += src_stride_argb4444; 1293 dst_argb += dst_stride_argb; 1294 } 1295 return 0; 1296} 1297 1298// Convert NV12 to ARGB. 1299LIBYUV_API 1300int NV12ToARGB(const uint8* src_y, 1301 int src_stride_y, 1302 const uint8* src_uv, 1303 int src_stride_uv, 1304 uint8* dst_argb, 1305 int dst_stride_argb, 1306 int width, 1307 int height) { 1308 int y; 1309 void (*NV12ToARGBRow)(const uint8* y_buf, const uint8* uv_buf, uint8* rgb_buf, 1310 const struct YuvConstants* yuvconstants, int width) = 1311 NV12ToARGBRow_C; 1312 if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) { 1313 return -1; 1314 } 1315 // Negative height means invert the image. 1316 if (height < 0) { 1317 height = -height; 1318 dst_argb = dst_argb + (height - 1) * dst_stride_argb; 1319 dst_stride_argb = -dst_stride_argb; 1320 } 1321#if defined(HAS_NV12TOARGBROW_SSSE3) 1322 if (TestCpuFlag(kCpuHasSSSE3)) { 1323 NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3; 1324 if (IS_ALIGNED(width, 8)) { 1325 NV12ToARGBRow = NV12ToARGBRow_SSSE3; 1326 } 1327 } 1328#endif 1329#if defined(HAS_NV12TOARGBROW_AVX2) 1330 if (TestCpuFlag(kCpuHasAVX2)) { 1331 NV12ToARGBRow = NV12ToARGBRow_Any_AVX2; 1332 if (IS_ALIGNED(width, 16)) { 1333 NV12ToARGBRow = NV12ToARGBRow_AVX2; 1334 } 1335 } 1336#endif 1337#if defined(HAS_NV12TOARGBROW_NEON) 1338 if (TestCpuFlag(kCpuHasNEON)) { 1339 NV12ToARGBRow = NV12ToARGBRow_Any_NEON; 1340 if (IS_ALIGNED(width, 8)) { 1341 NV12ToARGBRow = NV12ToARGBRow_NEON; 1342 } 1343 } 1344#endif 1345#if defined(HAS_NV12TOARGBROW_DSPR2) 1346 if (TestCpuFlag(kCpuHasDSPR2)) { 1347 NV12ToARGBRow = NV12ToARGBRow_Any_DSPR2; 1348 if (IS_ALIGNED(width, 8)) { 1349 NV12ToARGBRow = NV12ToARGBRow_DSPR2; 1350 } 1351 } 1352#endif 1353#if defined(HAS_NV12TOARGBROW_MSA) 1354 if (TestCpuFlag(kCpuHasMSA)) { 1355 NV12ToARGBRow = NV12ToARGBRow_Any_MSA; 1356 if (IS_ALIGNED(width, 8)) { 1357 NV12ToARGBRow = NV12ToARGBRow_MSA; 1358 } 1359 } 1360#endif 1361 1362 for (y = 0; y < height; ++y) { 1363 NV12ToARGBRow(src_y, src_uv, dst_argb, &kYuvI601Constants, width); 1364 dst_argb += dst_stride_argb; 1365 src_y += src_stride_y; 1366 if (y & 1) { 1367 src_uv += src_stride_uv; 1368 } 1369 } 1370 return 0; 1371} 1372 1373// Convert NV21 to ARGB. 1374LIBYUV_API 1375int NV21ToARGB(const uint8* src_y, 1376 int src_stride_y, 1377 const uint8* src_uv, 1378 int src_stride_uv, 1379 uint8* dst_argb, 1380 int dst_stride_argb, 1381 int width, 1382 int height) { 1383 int y; 1384 void (*NV21ToARGBRow)(const uint8* y_buf, const uint8* uv_buf, uint8* rgb_buf, 1385 const struct YuvConstants* yuvconstants, int width) = 1386 NV21ToARGBRow_C; 1387 if (!src_y || !src_uv || !dst_argb || width <= 0 || height == 0) { 1388 return -1; 1389 } 1390 // Negative height means invert the image. 1391 if (height < 0) { 1392 height = -height; 1393 dst_argb = dst_argb + (height - 1) * dst_stride_argb; 1394 dst_stride_argb = -dst_stride_argb; 1395 } 1396#if defined(HAS_NV21TOARGBROW_SSSE3) 1397 if (TestCpuFlag(kCpuHasSSSE3)) { 1398 NV21ToARGBRow = NV21ToARGBRow_Any_SSSE3; 1399 if (IS_ALIGNED(width, 8)) { 1400 NV21ToARGBRow = NV21ToARGBRow_SSSE3; 1401 } 1402 } 1403#endif 1404#if defined(HAS_NV21TOARGBROW_AVX2) 1405 if (TestCpuFlag(kCpuHasAVX2)) { 1406 NV21ToARGBRow = NV21ToARGBRow_Any_AVX2; 1407 if (IS_ALIGNED(width, 16)) { 1408 NV21ToARGBRow = NV21ToARGBRow_AVX2; 1409 } 1410 } 1411#endif 1412#if defined(HAS_NV21TOARGBROW_NEON) 1413 if (TestCpuFlag(kCpuHasNEON)) { 1414 NV21ToARGBRow = NV21ToARGBRow_Any_NEON; 1415 if (IS_ALIGNED(width, 8)) { 1416 NV21ToARGBRow = NV21ToARGBRow_NEON; 1417 } 1418 } 1419#endif 1420#if defined(HAS_NV21TOARGBROW_MSA) 1421 if (TestCpuFlag(kCpuHasMSA)) { 1422 NV21ToARGBRow = NV21ToARGBRow_Any_MSA; 1423 if (IS_ALIGNED(width, 8)) { 1424 NV21ToARGBRow = NV21ToARGBRow_MSA; 1425 } 1426 } 1427#endif 1428 1429 for (y = 0; y < height; ++y) { 1430 NV21ToARGBRow(src_y, src_uv, dst_argb, &kYuvI601Constants, width); 1431 dst_argb += dst_stride_argb; 1432 src_y += src_stride_y; 1433 if (y & 1) { 1434 src_uv += src_stride_uv; 1435 } 1436 } 1437 return 0; 1438} 1439 1440// Convert M420 to ARGB. 1441LIBYUV_API 1442int M420ToARGB(const uint8* src_m420, 1443 int src_stride_m420, 1444 uint8* dst_argb, 1445 int dst_stride_argb, 1446 int width, 1447 int height) { 1448 int y; 1449 void (*NV12ToARGBRow)(const uint8* y_buf, const uint8* uv_buf, uint8* rgb_buf, 1450 const struct YuvConstants* yuvconstants, int width) = 1451 NV12ToARGBRow_C; 1452 if (!src_m420 || !dst_argb || width <= 0 || height == 0) { 1453 return -1; 1454 } 1455 // Negative height means invert the image. 1456 if (height < 0) { 1457 height = -height; 1458 dst_argb = dst_argb + (height - 1) * dst_stride_argb; 1459 dst_stride_argb = -dst_stride_argb; 1460 } 1461#if defined(HAS_NV12TOARGBROW_SSSE3) 1462 if (TestCpuFlag(kCpuHasSSSE3)) { 1463 NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3; 1464 if (IS_ALIGNED(width, 8)) { 1465 NV12ToARGBRow = NV12ToARGBRow_SSSE3; 1466 } 1467 } 1468#endif 1469#if defined(HAS_NV12TOARGBROW_AVX2) 1470 if (TestCpuFlag(kCpuHasAVX2)) { 1471 NV12ToARGBRow = NV12ToARGBRow_Any_AVX2; 1472 if (IS_ALIGNED(width, 16)) { 1473 NV12ToARGBRow = NV12ToARGBRow_AVX2; 1474 } 1475 } 1476#endif 1477#if defined(HAS_NV12TOARGBROW_NEON) 1478 if (TestCpuFlag(kCpuHasNEON)) { 1479 NV12ToARGBRow = NV12ToARGBRow_Any_NEON; 1480 if (IS_ALIGNED(width, 8)) { 1481 NV12ToARGBRow = NV12ToARGBRow_NEON; 1482 } 1483 } 1484#endif 1485#if defined(HAS_NV12TOARGBROW_DSPR2) 1486 if (TestCpuFlag(kCpuHasDSPR2)) { 1487 NV12ToARGBRow = NV12ToARGBRow_Any_DSPR2; 1488 if (IS_ALIGNED(width, 8)) { 1489 NV12ToARGBRow = NV12ToARGBRow_DSPR2; 1490 } 1491 } 1492#endif 1493#if defined(HAS_NV12TOARGBROW_MSA) 1494 if (TestCpuFlag(kCpuHasMSA)) { 1495 NV12ToARGBRow = NV12ToARGBRow_Any_MSA; 1496 if (IS_ALIGNED(width, 8)) { 1497 NV12ToARGBRow = NV12ToARGBRow_MSA; 1498 } 1499 } 1500#endif 1501 1502 for (y = 0; y < height - 1; y += 2) { 1503 NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb, 1504 &kYuvI601Constants, width); 1505 NV12ToARGBRow(src_m420 + src_stride_m420, src_m420 + src_stride_m420 * 2, 1506 dst_argb + dst_stride_argb, &kYuvI601Constants, width); 1507 dst_argb += dst_stride_argb * 2; 1508 src_m420 += src_stride_m420 * 3; 1509 } 1510 if (height & 1) { 1511 NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb, 1512 &kYuvI601Constants, width); 1513 } 1514 return 0; 1515} 1516 1517// Convert YUY2 to ARGB. 1518LIBYUV_API 1519int YUY2ToARGB(const uint8* src_yuy2, 1520 int src_stride_yuy2, 1521 uint8* dst_argb, 1522 int dst_stride_argb, 1523 int width, 1524 int height) { 1525 int y; 1526 void (*YUY2ToARGBRow)(const uint8* src_yuy2, uint8* dst_argb, 1527 const struct YuvConstants* yuvconstants, int width) = 1528 YUY2ToARGBRow_C; 1529 if (!src_yuy2 || !dst_argb || width <= 0 || height == 0) { 1530 return -1; 1531 } 1532 // Negative height means invert the image. 1533 if (height < 0) { 1534 height = -height; 1535 src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2; 1536 src_stride_yuy2 = -src_stride_yuy2; 1537 } 1538 // Coalesce rows. 1539 if (src_stride_yuy2 == width * 2 && dst_stride_argb == width * 4) { 1540 width *= height; 1541 height = 1; 1542 src_stride_yuy2 = dst_stride_argb = 0; 1543 } 1544#if defined(HAS_YUY2TOARGBROW_SSSE3) 1545 if (TestCpuFlag(kCpuHasSSSE3)) { 1546 YUY2ToARGBRow = YUY2ToARGBRow_Any_SSSE3; 1547 if (IS_ALIGNED(width, 16)) { 1548 YUY2ToARGBRow = YUY2ToARGBRow_SSSE3; 1549 } 1550 } 1551#endif 1552#if defined(HAS_YUY2TOARGBROW_AVX2) 1553 if (TestCpuFlag(kCpuHasAVX2)) { 1554 YUY2ToARGBRow = YUY2ToARGBRow_Any_AVX2; 1555 if (IS_ALIGNED(width, 32)) { 1556 YUY2ToARGBRow = YUY2ToARGBRow_AVX2; 1557 } 1558 } 1559#endif 1560#if defined(HAS_YUY2TOARGBROW_NEON) 1561 if (TestCpuFlag(kCpuHasNEON)) { 1562 YUY2ToARGBRow = YUY2ToARGBRow_Any_NEON; 1563 if (IS_ALIGNED(width, 8)) { 1564 YUY2ToARGBRow = YUY2ToARGBRow_NEON; 1565 } 1566 } 1567#endif 1568#if defined(HAS_YUY2TOARGBROW_MSA) 1569 if (TestCpuFlag(kCpuHasMSA)) { 1570 YUY2ToARGBRow = YUY2ToARGBRow_Any_MSA; 1571 if (IS_ALIGNED(width, 8)) { 1572 YUY2ToARGBRow = YUY2ToARGBRow_MSA; 1573 } 1574 } 1575#endif 1576 for (y = 0; y < height; ++y) { 1577 YUY2ToARGBRow(src_yuy2, dst_argb, &kYuvI601Constants, width); 1578 src_yuy2 += src_stride_yuy2; 1579 dst_argb += dst_stride_argb; 1580 } 1581 return 0; 1582} 1583 1584// Convert UYVY to ARGB. 1585LIBYUV_API 1586int UYVYToARGB(const uint8* src_uyvy, 1587 int src_stride_uyvy, 1588 uint8* dst_argb, 1589 int dst_stride_argb, 1590 int width, 1591 int height) { 1592 int y; 1593 void (*UYVYToARGBRow)(const uint8* src_uyvy, uint8* dst_argb, 1594 const struct YuvConstants* yuvconstants, int width) = 1595 UYVYToARGBRow_C; 1596 if (!src_uyvy || !dst_argb || width <= 0 || height == 0) { 1597 return -1; 1598 } 1599 // Negative height means invert the image. 1600 if (height < 0) { 1601 height = -height; 1602 src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy; 1603 src_stride_uyvy = -src_stride_uyvy; 1604 } 1605 // Coalesce rows. 1606 if (src_stride_uyvy == width * 2 && dst_stride_argb == width * 4) { 1607 width *= height; 1608 height = 1; 1609 src_stride_uyvy = dst_stride_argb = 0; 1610 } 1611#if defined(HAS_UYVYTOARGBROW_SSSE3) 1612 if (TestCpuFlag(kCpuHasSSSE3)) { 1613 UYVYToARGBRow = UYVYToARGBRow_Any_SSSE3; 1614 if (IS_ALIGNED(width, 16)) { 1615 UYVYToARGBRow = UYVYToARGBRow_SSSE3; 1616 } 1617 } 1618#endif 1619#if defined(HAS_UYVYTOARGBROW_AVX2) 1620 if (TestCpuFlag(kCpuHasAVX2)) { 1621 UYVYToARGBRow = UYVYToARGBRow_Any_AVX2; 1622 if (IS_ALIGNED(width, 32)) { 1623 UYVYToARGBRow = UYVYToARGBRow_AVX2; 1624 } 1625 } 1626#endif 1627#if defined(HAS_UYVYTOARGBROW_NEON) 1628 if (TestCpuFlag(kCpuHasNEON)) { 1629 UYVYToARGBRow = UYVYToARGBRow_Any_NEON; 1630 if (IS_ALIGNED(width, 8)) { 1631 UYVYToARGBRow = UYVYToARGBRow_NEON; 1632 } 1633 } 1634#endif 1635#if defined(HAS_UYVYTOARGBROW_MSA) 1636 if (TestCpuFlag(kCpuHasMSA)) { 1637 UYVYToARGBRow = UYVYToARGBRow_Any_MSA; 1638 if (IS_ALIGNED(width, 8)) { 1639 UYVYToARGBRow = UYVYToARGBRow_MSA; 1640 } 1641 } 1642#endif 1643 for (y = 0; y < height; ++y) { 1644 UYVYToARGBRow(src_uyvy, dst_argb, &kYuvI601Constants, width); 1645 src_uyvy += src_stride_uyvy; 1646 dst_argb += dst_stride_argb; 1647 } 1648 return 0; 1649} 1650 1651#ifdef __cplusplus 1652} // extern "C" 1653} // namespace libyuv 1654#endif 1655