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