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 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, 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 51 static 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. 131 LIBYUV_API 132 int 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. 148 LIBYUV_API 149 int 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. 167 LIBYUV_API 168 int 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. 184 LIBYUV_API 185 int 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. 203 LIBYUV_API 204 int 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. 220 LIBYUV_API 221 int 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 239 static 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. 324 LIBYUV_API 325 int 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. 341 LIBYUV_API 342 int 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. 360 LIBYUV_API 361 int 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. 377 LIBYUV_API 378 int 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. 396 LIBYUV_API 397 int 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. 413 LIBYUV_API 414 int 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 432 static 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. 516 LIBYUV_API 517 int 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. 533 LIBYUV_API 534 int 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. 552 LIBYUV_API 553 int 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. 569 static 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. 692 LIBYUV_API 693 int 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. 713 LIBYUV_API 714 int 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. 735 LIBYUV_API 736 int 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. 802 LIBYUV_API 803 int 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. 868 static 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. 872 static 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. 876 static 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. 880 LIBYUV_API 881 int 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). 892 LIBYUV_API 893 int 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. 904 LIBYUV_API 905 int 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). 916 LIBYUV_API 917 int 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. 928 LIBYUV_API 929 int 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. 940 LIBYUV_API 941 int 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. 1007 LIBYUV_API 1008 int 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. 1074 LIBYUV_API 1075 int 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. 1149 LIBYUV_API 1150 int 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. 1224 LIBYUV_API 1225 int 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 with matrix 1299 static int NV12ToARGBMatrix(const uint8* src_y, 1300 int src_stride_y, 1301 const uint8* src_uv, 1302 int src_stride_uv, 1303 uint8* dst_argb, 1304 int dst_stride_argb, 1305 const struct YuvConstants* yuvconstants, 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, yuvconstants, 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 with matrix 1374 static int NV21ToARGBMatrix(const uint8* src_y, 1375 int src_stride_y, 1376 const uint8* src_uv, 1377 int src_stride_uv, 1378 uint8* dst_argb, 1379 int dst_stride_argb, 1380 const struct YuvConstants* yuvconstants, 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, yuvconstants, 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 NV12 to ARGB. 1441 LIBYUV_API 1442 int NV12ToARGB(const uint8* src_y, 1443 int src_stride_y, 1444 const uint8* src_uv, 1445 int src_stride_uv, 1446 uint8* dst_argb, 1447 int dst_stride_argb, 1448 int width, 1449 int height) { 1450 return NV12ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_argb, 1451 dst_stride_argb, &kYuvI601Constants, width, height); 1452 } 1453 1454 // Convert NV21 to ARGB. 1455 LIBYUV_API 1456 int NV21ToARGB(const uint8* src_y, 1457 int src_stride_y, 1458 const uint8* src_uv, 1459 int src_stride_uv, 1460 uint8* dst_argb, 1461 int dst_stride_argb, 1462 int width, 1463 int height) { 1464 return NV21ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_argb, 1465 dst_stride_argb, &kYuvI601Constants, width, height); 1466 } 1467 1468 // Convert NV12 to ABGR. 1469 // To output ABGR instead of ARGB swap the UV and use a mirrored yuv matrix. 1470 // To swap the UV use NV12 instead of NV21.LIBYUV_API 1471 LIBYUV_API 1472 int NV12ToABGR(const uint8* src_y, 1473 int src_stride_y, 1474 const uint8* src_uv, 1475 int src_stride_uv, 1476 uint8* dst_abgr, 1477 int dst_stride_abgr, 1478 int width, 1479 int height) { 1480 return NV21ToARGBMatrix(src_y, src_stride_y, src_uv, src_stride_uv, dst_abgr, 1481 dst_stride_abgr, &kYvuI601Constants, width, height); 1482 } 1483 1484 // Convert NV21 to ABGR. 1485 LIBYUV_API 1486 int NV21ToABGR(const uint8* src_y, 1487 int src_stride_y, 1488 const uint8* src_vu, 1489 int src_stride_vu, 1490 uint8* dst_abgr, 1491 int dst_stride_abgr, 1492 int width, 1493 int height) { 1494 return NV12ToARGBMatrix(src_y, src_stride_y, src_vu, src_stride_vu, dst_abgr, 1495 dst_stride_abgr, &kYvuI601Constants, width, height); 1496 } 1497 1498 // Convert M420 to ARGB. 1499 LIBYUV_API 1500 int M420ToARGB(const uint8* src_m420, 1501 int src_stride_m420, 1502 uint8* dst_argb, 1503 int dst_stride_argb, 1504 int width, 1505 int height) { 1506 int y; 1507 void (*NV12ToARGBRow)(const uint8* y_buf, const uint8* uv_buf, uint8* rgb_buf, 1508 const struct YuvConstants* yuvconstants, int width) = 1509 NV12ToARGBRow_C; 1510 if (!src_m420 || !dst_argb || width <= 0 || height == 0) { 1511 return -1; 1512 } 1513 // Negative height means invert the image. 1514 if (height < 0) { 1515 height = -height; 1516 dst_argb = dst_argb + (height - 1) * dst_stride_argb; 1517 dst_stride_argb = -dst_stride_argb; 1518 } 1519 #if defined(HAS_NV12TOARGBROW_SSSE3) 1520 if (TestCpuFlag(kCpuHasSSSE3)) { 1521 NV12ToARGBRow = NV12ToARGBRow_Any_SSSE3; 1522 if (IS_ALIGNED(width, 8)) { 1523 NV12ToARGBRow = NV12ToARGBRow_SSSE3; 1524 } 1525 } 1526 #endif 1527 #if defined(HAS_NV12TOARGBROW_AVX2) 1528 if (TestCpuFlag(kCpuHasAVX2)) { 1529 NV12ToARGBRow = NV12ToARGBRow_Any_AVX2; 1530 if (IS_ALIGNED(width, 16)) { 1531 NV12ToARGBRow = NV12ToARGBRow_AVX2; 1532 } 1533 } 1534 #endif 1535 #if defined(HAS_NV12TOARGBROW_NEON) 1536 if (TestCpuFlag(kCpuHasNEON)) { 1537 NV12ToARGBRow = NV12ToARGBRow_Any_NEON; 1538 if (IS_ALIGNED(width, 8)) { 1539 NV12ToARGBRow = NV12ToARGBRow_NEON; 1540 } 1541 } 1542 #endif 1543 #if defined(HAS_NV12TOARGBROW_DSPR2) 1544 if (TestCpuFlag(kCpuHasDSPR2)) { 1545 NV12ToARGBRow = NV12ToARGBRow_Any_DSPR2; 1546 if (IS_ALIGNED(width, 8)) { 1547 NV12ToARGBRow = NV12ToARGBRow_DSPR2; 1548 } 1549 } 1550 #endif 1551 #if defined(HAS_NV12TOARGBROW_MSA) 1552 if (TestCpuFlag(kCpuHasMSA)) { 1553 NV12ToARGBRow = NV12ToARGBRow_Any_MSA; 1554 if (IS_ALIGNED(width, 8)) { 1555 NV12ToARGBRow = NV12ToARGBRow_MSA; 1556 } 1557 } 1558 #endif 1559 1560 for (y = 0; y < height - 1; y += 2) { 1561 NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb, 1562 &kYuvI601Constants, width); 1563 NV12ToARGBRow(src_m420 + src_stride_m420, src_m420 + src_stride_m420 * 2, 1564 dst_argb + dst_stride_argb, &kYuvI601Constants, width); 1565 dst_argb += dst_stride_argb * 2; 1566 src_m420 += src_stride_m420 * 3; 1567 } 1568 if (height & 1) { 1569 NV12ToARGBRow(src_m420, src_m420 + src_stride_m420 * 2, dst_argb, 1570 &kYuvI601Constants, width); 1571 } 1572 return 0; 1573 } 1574 1575 // Convert YUY2 to ARGB. 1576 LIBYUV_API 1577 int YUY2ToARGB(const uint8* src_yuy2, 1578 int src_stride_yuy2, 1579 uint8* dst_argb, 1580 int dst_stride_argb, 1581 int width, 1582 int height) { 1583 int y; 1584 void (*YUY2ToARGBRow)(const uint8* src_yuy2, uint8* dst_argb, 1585 const struct YuvConstants* yuvconstants, int width) = 1586 YUY2ToARGBRow_C; 1587 if (!src_yuy2 || !dst_argb || width <= 0 || height == 0) { 1588 return -1; 1589 } 1590 // Negative height means invert the image. 1591 if (height < 0) { 1592 height = -height; 1593 src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2; 1594 src_stride_yuy2 = -src_stride_yuy2; 1595 } 1596 // Coalesce rows. 1597 if (src_stride_yuy2 == width * 2 && dst_stride_argb == width * 4) { 1598 width *= height; 1599 height = 1; 1600 src_stride_yuy2 = dst_stride_argb = 0; 1601 } 1602 #if defined(HAS_YUY2TOARGBROW_SSSE3) 1603 if (TestCpuFlag(kCpuHasSSSE3)) { 1604 YUY2ToARGBRow = YUY2ToARGBRow_Any_SSSE3; 1605 if (IS_ALIGNED(width, 16)) { 1606 YUY2ToARGBRow = YUY2ToARGBRow_SSSE3; 1607 } 1608 } 1609 #endif 1610 #if defined(HAS_YUY2TOARGBROW_AVX2) 1611 if (TestCpuFlag(kCpuHasAVX2)) { 1612 YUY2ToARGBRow = YUY2ToARGBRow_Any_AVX2; 1613 if (IS_ALIGNED(width, 32)) { 1614 YUY2ToARGBRow = YUY2ToARGBRow_AVX2; 1615 } 1616 } 1617 #endif 1618 #if defined(HAS_YUY2TOARGBROW_NEON) 1619 if (TestCpuFlag(kCpuHasNEON)) { 1620 YUY2ToARGBRow = YUY2ToARGBRow_Any_NEON; 1621 if (IS_ALIGNED(width, 8)) { 1622 YUY2ToARGBRow = YUY2ToARGBRow_NEON; 1623 } 1624 } 1625 #endif 1626 #if defined(HAS_YUY2TOARGBROW_MSA) 1627 if (TestCpuFlag(kCpuHasMSA)) { 1628 YUY2ToARGBRow = YUY2ToARGBRow_Any_MSA; 1629 if (IS_ALIGNED(width, 8)) { 1630 YUY2ToARGBRow = YUY2ToARGBRow_MSA; 1631 } 1632 } 1633 #endif 1634 for (y = 0; y < height; ++y) { 1635 YUY2ToARGBRow(src_yuy2, dst_argb, &kYuvI601Constants, width); 1636 src_yuy2 += src_stride_yuy2; 1637 dst_argb += dst_stride_argb; 1638 } 1639 return 0; 1640 } 1641 1642 // Convert UYVY to ARGB. 1643 LIBYUV_API 1644 int UYVYToARGB(const uint8* src_uyvy, 1645 int src_stride_uyvy, 1646 uint8* dst_argb, 1647 int dst_stride_argb, 1648 int width, 1649 int height) { 1650 int y; 1651 void (*UYVYToARGBRow)(const uint8* src_uyvy, uint8* dst_argb, 1652 const struct YuvConstants* yuvconstants, int width) = 1653 UYVYToARGBRow_C; 1654 if (!src_uyvy || !dst_argb || width <= 0 || height == 0) { 1655 return -1; 1656 } 1657 // Negative height means invert the image. 1658 if (height < 0) { 1659 height = -height; 1660 src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy; 1661 src_stride_uyvy = -src_stride_uyvy; 1662 } 1663 // Coalesce rows. 1664 if (src_stride_uyvy == width * 2 && dst_stride_argb == width * 4) { 1665 width *= height; 1666 height = 1; 1667 src_stride_uyvy = dst_stride_argb = 0; 1668 } 1669 #if defined(HAS_UYVYTOARGBROW_SSSE3) 1670 if (TestCpuFlag(kCpuHasSSSE3)) { 1671 UYVYToARGBRow = UYVYToARGBRow_Any_SSSE3; 1672 if (IS_ALIGNED(width, 16)) { 1673 UYVYToARGBRow = UYVYToARGBRow_SSSE3; 1674 } 1675 } 1676 #endif 1677 #if defined(HAS_UYVYTOARGBROW_AVX2) 1678 if (TestCpuFlag(kCpuHasAVX2)) { 1679 UYVYToARGBRow = UYVYToARGBRow_Any_AVX2; 1680 if (IS_ALIGNED(width, 32)) { 1681 UYVYToARGBRow = UYVYToARGBRow_AVX2; 1682 } 1683 } 1684 #endif 1685 #if defined(HAS_UYVYTOARGBROW_NEON) 1686 if (TestCpuFlag(kCpuHasNEON)) { 1687 UYVYToARGBRow = UYVYToARGBRow_Any_NEON; 1688 if (IS_ALIGNED(width, 8)) { 1689 UYVYToARGBRow = UYVYToARGBRow_NEON; 1690 } 1691 } 1692 #endif 1693 #if defined(HAS_UYVYTOARGBROW_MSA) 1694 if (TestCpuFlag(kCpuHasMSA)) { 1695 UYVYToARGBRow = UYVYToARGBRow_Any_MSA; 1696 if (IS_ALIGNED(width, 8)) { 1697 UYVYToARGBRow = UYVYToARGBRow_MSA; 1698 } 1699 } 1700 #endif 1701 for (y = 0; y < height; ++y) { 1702 UYVYToARGBRow(src_uyvy, dst_argb, &kYuvI601Constants, width); 1703 src_uyvy += src_stride_uyvy; 1704 dst_argb += dst_stride_argb; 1705 } 1706 return 0; 1707 } 1708 static void WeavePixels(const uint8* src_u, 1709 const uint8* src_v, 1710 int src_pixel_stride_uv, 1711 uint8* dst_uv, 1712 int width) { 1713 int i; 1714 for (i = 0; i < width; ++i) { 1715 dst_uv[0] = *src_u; 1716 dst_uv[1] = *src_v; 1717 dst_uv += 2; 1718 src_u += src_pixel_stride_uv; 1719 src_v += src_pixel_stride_uv; 1720 } 1721 } 1722 1723 // Convert Android420 to ARGB. 1724 LIBYUV_API 1725 int Android420ToARGBMatrix(const uint8* src_y, 1726 int src_stride_y, 1727 const uint8* src_u, 1728 int src_stride_u, 1729 const uint8* src_v, 1730 int src_stride_v, 1731 int src_pixel_stride_uv, 1732 uint8* dst_argb, 1733 int dst_stride_argb, 1734 const struct YuvConstants* yuvconstants, 1735 int width, 1736 int height) { 1737 int y; 1738 uint8* dst_uv; 1739 const ptrdiff_t vu_off = src_v - src_u; 1740 int halfwidth = (width + 1) >> 1; 1741 int halfheight = (height + 1) >> 1; 1742 if (!src_y || !src_u || !src_v || !dst_argb || width <= 0 || height == 0) { 1743 return -1; 1744 } 1745 // Negative height means invert the image. 1746 if (height < 0) { 1747 height = -height; 1748 halfheight = (height + 1) >> 1; 1749 dst_argb = dst_argb + (height - 1) * dst_stride_argb; 1750 dst_stride_argb = -dst_stride_argb; 1751 } 1752 1753 // I420 1754 if (src_pixel_stride_uv == 1) { 1755 return I420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v, 1756 src_stride_v, dst_argb, dst_stride_argb, 1757 yuvconstants, width, height); 1758 // NV21 1759 } else if (src_pixel_stride_uv == 2 && vu_off == -1 && 1760 src_stride_u == src_stride_v) { 1761 return NV21ToARGBMatrix(src_y, src_stride_y, src_v, src_stride_v, dst_argb, 1762 dst_stride_argb, yuvconstants, width, height); 1763 // NV12 1764 } else if (src_pixel_stride_uv == 2 && vu_off == 1 && 1765 src_stride_u == src_stride_v) { 1766 return NV12ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, dst_argb, 1767 dst_stride_argb, yuvconstants, width, height); 1768 } 1769 1770 // General case fallback creates NV12 1771 align_buffer_64(plane_uv, halfwidth * 2 * halfheight); 1772 dst_uv = plane_uv; 1773 for (y = 0; y < halfheight; ++y) { 1774 WeavePixels(src_u, src_v, src_pixel_stride_uv, dst_uv, halfwidth); 1775 src_u += src_stride_u; 1776 src_v += src_stride_v; 1777 dst_uv += halfwidth * 2; 1778 } 1779 NV12ToARGBMatrix(src_y, src_stride_y, plane_uv, halfwidth * 2, dst_argb, 1780 dst_stride_argb, yuvconstants, width, height); 1781 free_aligned_buffer_64(plane_uv); 1782 return 0; 1783 } 1784 1785 // Convert Android420 to ARGB. 1786 LIBYUV_API 1787 int Android420ToARGB(const uint8* src_y, 1788 int src_stride_y, 1789 const uint8* src_u, 1790 int src_stride_u, 1791 const uint8* src_v, 1792 int src_stride_v, 1793 int src_pixel_stride_uv, 1794 uint8* dst_argb, 1795 int dst_stride_argb, 1796 int width, 1797 int height) { 1798 return Android420ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, src_v, 1799 src_stride_v, src_pixel_stride_uv, dst_argb, 1800 dst_stride_argb, &kYuvI601Constants, width, 1801 height); 1802 } 1803 1804 // Convert Android420 to ABGR. 1805 LIBYUV_API 1806 int Android420ToABGR(const uint8* src_y, 1807 int src_stride_y, 1808 const uint8* src_u, 1809 int src_stride_u, 1810 const uint8* src_v, 1811 int src_stride_v, 1812 int src_pixel_stride_uv, 1813 uint8* dst_abgr, 1814 int dst_stride_abgr, 1815 int width, 1816 int height) { 1817 return Android420ToARGBMatrix(src_y, src_stride_y, src_v, src_stride_v, src_u, 1818 src_stride_u, src_pixel_stride_uv, dst_abgr, 1819 dst_stride_abgr, &kYvuI601Constants, width, 1820 height); 1821 } 1822 1823 #ifdef __cplusplus 1824 } // extern "C" 1825 } // namespace libyuv 1826 #endif 1827