1 /* 2 * Copyright 2012 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_from_argb.h" 12 13 #include "libyuv/basic_types.h" 14 #include "libyuv/cpu_id.h" 15 #include "libyuv/planar_functions.h" 16 #include "libyuv/row.h" 17 18 #ifdef __cplusplus 19 namespace libyuv { 20 extern "C" { 21 #endif 22 23 // ARGB little endian (bgra in memory) to I444 24 LIBYUV_API 25 int ARGBToI444(const uint8* src_argb, int src_stride_argb, 26 uint8* dst_y, int dst_stride_y, 27 uint8* dst_u, int dst_stride_u, 28 uint8* dst_v, int dst_stride_v, 29 int width, int height) { 30 int y; 31 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = 32 ARGBToYRow_C; 33 void (*ARGBToUV444Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v, 34 int pix) = ARGBToUV444Row_C; 35 if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) { 36 return -1; 37 } 38 if (height < 0) { 39 height = -height; 40 src_argb = src_argb + (height - 1) * src_stride_argb; 41 src_stride_argb = -src_stride_argb; 42 } 43 // Coalesce rows. 44 if (src_stride_argb == width * 4 && 45 dst_stride_y == width && 46 dst_stride_u == width && 47 dst_stride_v == width) { 48 width *= height; 49 height = 1; 50 src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0; 51 } 52 #if defined(HAS_ARGBTOUV444ROW_SSSE3) 53 if (TestCpuFlag(kCpuHasSSSE3)) { 54 ARGBToUV444Row = ARGBToUV444Row_Any_SSSE3; 55 if (IS_ALIGNED(width, 16)) { 56 ARGBToUV444Row = ARGBToUV444Row_SSSE3; 57 } 58 } 59 #endif 60 #if defined(HAS_ARGBTOUV444ROW_NEON) 61 if (TestCpuFlag(kCpuHasNEON)) { 62 ARGBToUV444Row = ARGBToUV444Row_Any_NEON; 63 if (IS_ALIGNED(width, 8)) { 64 ARGBToUV444Row = ARGBToUV444Row_NEON; 65 } 66 } 67 #endif 68 #if defined(HAS_ARGBTOYROW_SSSE3) 69 if (TestCpuFlag(kCpuHasSSSE3)) { 70 ARGBToYRow = ARGBToYRow_Any_SSSE3; 71 if (IS_ALIGNED(width, 16)) { 72 ARGBToYRow = ARGBToYRow_SSSE3; 73 } 74 } 75 #endif 76 #if defined(HAS_ARGBTOYROW_AVX2) 77 if (TestCpuFlag(kCpuHasAVX2)) { 78 ARGBToYRow = ARGBToYRow_Any_AVX2; 79 if (IS_ALIGNED(width, 32)) { 80 ARGBToYRow = ARGBToYRow_AVX2; 81 } 82 } 83 #endif 84 #if defined(HAS_ARGBTOYROW_NEON) 85 if (TestCpuFlag(kCpuHasNEON)) { 86 ARGBToYRow = ARGBToYRow_Any_NEON; 87 if (IS_ALIGNED(width, 8)) { 88 ARGBToYRow = ARGBToYRow_NEON; 89 } 90 } 91 #endif 92 93 for (y = 0; y < height; ++y) { 94 ARGBToUV444Row(src_argb, dst_u, dst_v, width); 95 ARGBToYRow(src_argb, dst_y, width); 96 src_argb += src_stride_argb; 97 dst_y += dst_stride_y; 98 dst_u += dst_stride_u; 99 dst_v += dst_stride_v; 100 } 101 return 0; 102 } 103 104 // ARGB little endian (bgra in memory) to I422 105 LIBYUV_API 106 int ARGBToI422(const uint8* src_argb, int src_stride_argb, 107 uint8* dst_y, int dst_stride_y, 108 uint8* dst_u, int dst_stride_u, 109 uint8* dst_v, int dst_stride_v, 110 int width, int height) { 111 int y; 112 void (*ARGBToUV422Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v, 113 int pix) = ARGBToUV422Row_C; 114 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = 115 ARGBToYRow_C; 116 if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) { 117 return -1; 118 } 119 if (height < 0) { 120 height = -height; 121 src_argb = src_argb + (height - 1) * src_stride_argb; 122 src_stride_argb = -src_stride_argb; 123 } 124 // Coalesce rows. 125 if (src_stride_argb == width * 4 && 126 dst_stride_y == width && 127 dst_stride_u * 2 == width && 128 dst_stride_v * 2 == width) { 129 width *= height; 130 height = 1; 131 src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0; 132 } 133 #if defined(HAS_ARGBTOUV422ROW_SSSE3) 134 if (TestCpuFlag(kCpuHasSSSE3)) { 135 ARGBToUV422Row = ARGBToUV422Row_Any_SSSE3; 136 if (IS_ALIGNED(width, 16)) { 137 ARGBToUV422Row = ARGBToUV422Row_SSSE3; 138 } 139 } 140 #endif 141 #if defined(HAS_ARGBTOUV422ROW_NEON) 142 if (TestCpuFlag(kCpuHasNEON)) { 143 ARGBToUV422Row = ARGBToUV422Row_Any_NEON; 144 if (IS_ALIGNED(width, 16)) { 145 ARGBToUV422Row = ARGBToUV422Row_NEON; 146 } 147 } 148 #endif 149 #if defined(HAS_ARGBTOYROW_SSSE3) 150 if (TestCpuFlag(kCpuHasSSSE3)) { 151 ARGBToYRow = ARGBToYRow_Any_SSSE3; 152 if (IS_ALIGNED(width, 16)) { 153 ARGBToYRow = ARGBToYRow_SSSE3; 154 } 155 } 156 #endif 157 #if defined(HAS_ARGBTOYROW_AVX2) 158 if (TestCpuFlag(kCpuHasAVX2)) { 159 ARGBToYRow = ARGBToYRow_Any_AVX2; 160 if (IS_ALIGNED(width, 32)) { 161 ARGBToYRow = ARGBToYRow_AVX2; 162 } 163 } 164 #endif 165 #if defined(HAS_ARGBTOYROW_NEON) 166 if (TestCpuFlag(kCpuHasNEON)) { 167 ARGBToYRow = ARGBToYRow_Any_NEON; 168 if (IS_ALIGNED(width, 8)) { 169 ARGBToYRow = ARGBToYRow_NEON; 170 } 171 } 172 #endif 173 174 for (y = 0; y < height; ++y) { 175 ARGBToUV422Row(src_argb, dst_u, dst_v, width); 176 ARGBToYRow(src_argb, dst_y, width); 177 src_argb += src_stride_argb; 178 dst_y += dst_stride_y; 179 dst_u += dst_stride_u; 180 dst_v += dst_stride_v; 181 } 182 return 0; 183 } 184 185 // ARGB little endian (bgra in memory) to I411 186 LIBYUV_API 187 int ARGBToI411(const uint8* src_argb, int src_stride_argb, 188 uint8* dst_y, int dst_stride_y, 189 uint8* dst_u, int dst_stride_u, 190 uint8* dst_v, int dst_stride_v, 191 int width, int height) { 192 int y; 193 void (*ARGBToUV411Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v, 194 int pix) = ARGBToUV411Row_C; 195 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = 196 ARGBToYRow_C; 197 if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) { 198 return -1; 199 } 200 if (height < 0) { 201 height = -height; 202 src_argb = src_argb + (height - 1) * src_stride_argb; 203 src_stride_argb = -src_stride_argb; 204 } 205 // Coalesce rows. 206 if (src_stride_argb == width * 4 && 207 dst_stride_y == width && 208 dst_stride_u * 4 == width && 209 dst_stride_v * 4 == width) { 210 width *= height; 211 height = 1; 212 src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0; 213 } 214 #if defined(HAS_ARGBTOYROW_SSSE3) 215 if (TestCpuFlag(kCpuHasSSSE3)) { 216 ARGBToYRow = ARGBToYRow_Any_SSSE3; 217 if (IS_ALIGNED(width, 16)) { 218 ARGBToYRow = ARGBToYRow_SSSE3; 219 } 220 } 221 #endif 222 #if defined(HAS_ARGBTOYROW_AVX2) 223 if (TestCpuFlag(kCpuHasAVX2)) { 224 ARGBToYRow = ARGBToYRow_Any_AVX2; 225 if (IS_ALIGNED(width, 32)) { 226 ARGBToYRow = ARGBToYRow_AVX2; 227 } 228 } 229 #endif 230 #if defined(HAS_ARGBTOYROW_NEON) 231 if (TestCpuFlag(kCpuHasNEON)) { 232 ARGBToYRow = ARGBToYRow_Any_NEON; 233 if (IS_ALIGNED(width, 8)) { 234 ARGBToYRow = ARGBToYRow_NEON; 235 } 236 } 237 #endif 238 #if defined(HAS_ARGBTOUV411ROW_NEON) 239 if (TestCpuFlag(kCpuHasNEON)) { 240 ARGBToUV411Row = ARGBToUV411Row_Any_NEON; 241 if (IS_ALIGNED(width, 32)) { 242 ARGBToUV411Row = ARGBToUV411Row_NEON; 243 } 244 } 245 #endif 246 247 for (y = 0; y < height; ++y) { 248 ARGBToUV411Row(src_argb, dst_u, dst_v, width); 249 ARGBToYRow(src_argb, dst_y, width); 250 src_argb += src_stride_argb; 251 dst_y += dst_stride_y; 252 dst_u += dst_stride_u; 253 dst_v += dst_stride_v; 254 } 255 return 0; 256 } 257 258 LIBYUV_API 259 int ARGBToNV12(const uint8* src_argb, int src_stride_argb, 260 uint8* dst_y, int dst_stride_y, 261 uint8* dst_uv, int dst_stride_uv, 262 int width, int height) { 263 int y; 264 int halfwidth = (width + 1) >> 1; 265 void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, 266 uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C; 267 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = 268 ARGBToYRow_C; 269 void (*MergeUVRow_)(const uint8* src_u, const uint8* src_v, uint8* dst_uv, 270 int width) = MergeUVRow_C; 271 if (!src_argb || 272 !dst_y || !dst_uv || 273 width <= 0 || height == 0) { 274 return -1; 275 } 276 // Negative height means invert the image. 277 if (height < 0) { 278 height = -height; 279 src_argb = src_argb + (height - 1) * src_stride_argb; 280 src_stride_argb = -src_stride_argb; 281 } 282 #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3) 283 if (TestCpuFlag(kCpuHasSSSE3)) { 284 ARGBToUVRow = ARGBToUVRow_Any_SSSE3; 285 ARGBToYRow = ARGBToYRow_Any_SSSE3; 286 if (IS_ALIGNED(width, 16)) { 287 ARGBToUVRow = ARGBToUVRow_SSSE3; 288 ARGBToYRow = ARGBToYRow_SSSE3; 289 } 290 } 291 #endif 292 #if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2) 293 if (TestCpuFlag(kCpuHasAVX2)) { 294 ARGBToUVRow = ARGBToUVRow_Any_AVX2; 295 ARGBToYRow = ARGBToYRow_Any_AVX2; 296 if (IS_ALIGNED(width, 32)) { 297 ARGBToUVRow = ARGBToUVRow_AVX2; 298 ARGBToYRow = ARGBToYRow_AVX2; 299 } 300 } 301 #endif 302 #if defined(HAS_ARGBTOYROW_NEON) 303 if (TestCpuFlag(kCpuHasNEON)) { 304 ARGBToYRow = ARGBToYRow_Any_NEON; 305 if (IS_ALIGNED(width, 8)) { 306 ARGBToYRow = ARGBToYRow_NEON; 307 } 308 } 309 #endif 310 #if defined(HAS_ARGBTOUVROW_NEON) 311 if (TestCpuFlag(kCpuHasNEON)) { 312 ARGBToUVRow = ARGBToUVRow_Any_NEON; 313 if (IS_ALIGNED(width, 16)) { 314 ARGBToUVRow = ARGBToUVRow_NEON; 315 } 316 } 317 #endif 318 #if defined(HAS_MERGEUVROW_SSE2) 319 if (TestCpuFlag(kCpuHasSSE2)) { 320 MergeUVRow_ = MergeUVRow_Any_SSE2; 321 if (IS_ALIGNED(halfwidth, 16)) { 322 MergeUVRow_ = MergeUVRow_SSE2; 323 } 324 } 325 #endif 326 #if defined(HAS_MERGEUVROW_AVX2) 327 if (TestCpuFlag(kCpuHasAVX2)) { 328 MergeUVRow_ = MergeUVRow_Any_AVX2; 329 if (IS_ALIGNED(halfwidth, 32)) { 330 MergeUVRow_ = MergeUVRow_AVX2; 331 } 332 } 333 #endif 334 #if defined(HAS_MERGEUVROW_NEON) 335 if (TestCpuFlag(kCpuHasNEON)) { 336 MergeUVRow_ = MergeUVRow_Any_NEON; 337 if (IS_ALIGNED(halfwidth, 16)) { 338 MergeUVRow_ = MergeUVRow_NEON; 339 } 340 } 341 #endif 342 { 343 // Allocate a rows of uv. 344 align_buffer_64(row_u, ((halfwidth + 31) & ~31) * 2); 345 uint8* row_v = row_u + ((halfwidth + 31) & ~31); 346 347 for (y = 0; y < height - 1; y += 2) { 348 ARGBToUVRow(src_argb, src_stride_argb, row_u, row_v, width); 349 MergeUVRow_(row_u, row_v, dst_uv, halfwidth); 350 ARGBToYRow(src_argb, dst_y, width); 351 ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width); 352 src_argb += src_stride_argb * 2; 353 dst_y += dst_stride_y * 2; 354 dst_uv += dst_stride_uv; 355 } 356 if (height & 1) { 357 ARGBToUVRow(src_argb, 0, row_u, row_v, width); 358 MergeUVRow_(row_u, row_v, dst_uv, halfwidth); 359 ARGBToYRow(src_argb, dst_y, width); 360 } 361 free_aligned_buffer_64(row_u); 362 } 363 return 0; 364 } 365 366 // Same as NV12 but U and V swapped. 367 LIBYUV_API 368 int ARGBToNV21(const uint8* src_argb, int src_stride_argb, 369 uint8* dst_y, int dst_stride_y, 370 uint8* dst_uv, int dst_stride_uv, 371 int width, int height) { 372 int y; 373 int halfwidth = (width + 1) >> 1; 374 void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, 375 uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C; 376 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = 377 ARGBToYRow_C; 378 void (*MergeUVRow_)(const uint8* src_u, const uint8* src_v, uint8* dst_uv, 379 int width) = MergeUVRow_C; 380 if (!src_argb || 381 !dst_y || !dst_uv || 382 width <= 0 || height == 0) { 383 return -1; 384 } 385 // Negative height means invert the image. 386 if (height < 0) { 387 height = -height; 388 src_argb = src_argb + (height - 1) * src_stride_argb; 389 src_stride_argb = -src_stride_argb; 390 } 391 #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3) 392 if (TestCpuFlag(kCpuHasSSSE3)) { 393 ARGBToUVRow = ARGBToUVRow_Any_SSSE3; 394 ARGBToYRow = ARGBToYRow_Any_SSSE3; 395 if (IS_ALIGNED(width, 16)) { 396 ARGBToUVRow = ARGBToUVRow_SSSE3; 397 ARGBToYRow = ARGBToYRow_SSSE3; 398 } 399 } 400 #endif 401 #if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2) 402 if (TestCpuFlag(kCpuHasAVX2)) { 403 ARGBToUVRow = ARGBToUVRow_Any_AVX2; 404 ARGBToYRow = ARGBToYRow_Any_AVX2; 405 if (IS_ALIGNED(width, 32)) { 406 ARGBToUVRow = ARGBToUVRow_AVX2; 407 ARGBToYRow = ARGBToYRow_AVX2; 408 } 409 } 410 #endif 411 #if defined(HAS_ARGBTOYROW_NEON) 412 if (TestCpuFlag(kCpuHasNEON)) { 413 ARGBToYRow = ARGBToYRow_Any_NEON; 414 if (IS_ALIGNED(width, 8)) { 415 ARGBToYRow = ARGBToYRow_NEON; 416 } 417 } 418 #endif 419 #if defined(HAS_ARGBTOUVROW_NEON) 420 if (TestCpuFlag(kCpuHasNEON)) { 421 ARGBToUVRow = ARGBToUVRow_Any_NEON; 422 if (IS_ALIGNED(width, 16)) { 423 ARGBToUVRow = ARGBToUVRow_NEON; 424 } 425 } 426 #endif 427 #if defined(HAS_MERGEUVROW_SSE2) 428 if (TestCpuFlag(kCpuHasSSE2)) { 429 MergeUVRow_ = MergeUVRow_Any_SSE2; 430 if (IS_ALIGNED(halfwidth, 16)) { 431 MergeUVRow_ = MergeUVRow_SSE2; 432 } 433 } 434 #endif 435 #if defined(HAS_MERGEUVROW_AVX2) 436 if (TestCpuFlag(kCpuHasAVX2)) { 437 MergeUVRow_ = MergeUVRow_Any_AVX2; 438 if (IS_ALIGNED(halfwidth, 32)) { 439 MergeUVRow_ = MergeUVRow_AVX2; 440 } 441 } 442 #endif 443 #if defined(HAS_MERGEUVROW_NEON) 444 if (TestCpuFlag(kCpuHasNEON)) { 445 MergeUVRow_ = MergeUVRow_Any_NEON; 446 if (IS_ALIGNED(halfwidth, 16)) { 447 MergeUVRow_ = MergeUVRow_NEON; 448 } 449 } 450 #endif 451 { 452 // Allocate a rows of uv. 453 align_buffer_64(row_u, ((halfwidth + 31) & ~31) * 2); 454 uint8* row_v = row_u + ((halfwidth + 31) & ~31); 455 456 for (y = 0; y < height - 1; y += 2) { 457 ARGBToUVRow(src_argb, src_stride_argb, row_u, row_v, width); 458 MergeUVRow_(row_v, row_u, dst_uv, halfwidth); 459 ARGBToYRow(src_argb, dst_y, width); 460 ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width); 461 src_argb += src_stride_argb * 2; 462 dst_y += dst_stride_y * 2; 463 dst_uv += dst_stride_uv; 464 } 465 if (height & 1) { 466 ARGBToUVRow(src_argb, 0, row_u, row_v, width); 467 MergeUVRow_(row_v, row_u, dst_uv, halfwidth); 468 ARGBToYRow(src_argb, dst_y, width); 469 } 470 free_aligned_buffer_64(row_u); 471 } 472 return 0; 473 } 474 475 // Convert ARGB to YUY2. 476 LIBYUV_API 477 int ARGBToYUY2(const uint8* src_argb, int src_stride_argb, 478 uint8* dst_yuy2, int dst_stride_yuy2, 479 int width, int height) { 480 int y; 481 void (*ARGBToUV422Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v, 482 int pix) = ARGBToUV422Row_C; 483 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = 484 ARGBToYRow_C; 485 void (*I422ToYUY2Row)(const uint8* src_y, const uint8* src_u, 486 const uint8* src_v, uint8* dst_yuy2, int width) = I422ToYUY2Row_C; 487 488 if (!src_argb || !dst_yuy2 || 489 width <= 0 || height == 0) { 490 return -1; 491 } 492 // Negative height means invert the image. 493 if (height < 0) { 494 height = -height; 495 dst_yuy2 = dst_yuy2 + (height - 1) * dst_stride_yuy2; 496 dst_stride_yuy2 = -dst_stride_yuy2; 497 } 498 // Coalesce rows. 499 if (src_stride_argb == width * 4 && 500 dst_stride_yuy2 == width * 2) { 501 width *= height; 502 height = 1; 503 src_stride_argb = dst_stride_yuy2 = 0; 504 } 505 #if defined(HAS_ARGBTOUV422ROW_SSSE3) 506 if (TestCpuFlag(kCpuHasSSSE3)) { 507 ARGBToUV422Row = ARGBToUV422Row_Any_SSSE3; 508 if (IS_ALIGNED(width, 16)) { 509 ARGBToUV422Row = ARGBToUV422Row_SSSE3; 510 } 511 } 512 #endif 513 #if defined(HAS_ARGBTOUV422ROW_NEON) 514 if (TestCpuFlag(kCpuHasNEON)) { 515 ARGBToUV422Row = ARGBToUV422Row_Any_NEON; 516 if (IS_ALIGNED(width, 16)) { 517 ARGBToUV422Row = ARGBToUV422Row_NEON; 518 } 519 } 520 #endif 521 #if defined(HAS_ARGBTOYROW_SSSE3) 522 if (TestCpuFlag(kCpuHasSSSE3)) { 523 ARGBToYRow = ARGBToYRow_Any_SSSE3; 524 if (IS_ALIGNED(width, 16)) { 525 ARGBToYRow = ARGBToYRow_SSSE3; 526 } 527 } 528 #endif 529 #if defined(HAS_ARGBTOYROW_AVX2) 530 if (TestCpuFlag(kCpuHasAVX2)) { 531 ARGBToYRow = ARGBToYRow_Any_AVX2; 532 if (IS_ALIGNED(width, 32)) { 533 ARGBToYRow = ARGBToYRow_AVX2; 534 } 535 } 536 #endif 537 #if defined(HAS_ARGBTOYROW_NEON) 538 if (TestCpuFlag(kCpuHasNEON)) { 539 ARGBToYRow = ARGBToYRow_Any_NEON; 540 if (IS_ALIGNED(width, 8)) { 541 ARGBToYRow = ARGBToYRow_NEON; 542 } 543 } 544 #endif 545 546 #if defined(HAS_I422TOYUY2ROW_SSE2) 547 if (TestCpuFlag(kCpuHasSSE2)) { 548 I422ToYUY2Row = I422ToYUY2Row_Any_SSE2; 549 if (IS_ALIGNED(width, 16)) { 550 I422ToYUY2Row = I422ToYUY2Row_SSE2; 551 } 552 } 553 #endif 554 #if defined(HAS_I422TOYUY2ROW_NEON) 555 if (TestCpuFlag(kCpuHasNEON)) { 556 I422ToYUY2Row = I422ToYUY2Row_Any_NEON; 557 if (IS_ALIGNED(width, 16)) { 558 I422ToYUY2Row = I422ToYUY2Row_NEON; 559 } 560 } 561 #endif 562 563 { 564 // Allocate a rows of yuv. 565 align_buffer_64(row_y, ((width + 63) & ~63) * 2); 566 uint8* row_u = row_y + ((width + 63) & ~63); 567 uint8* row_v = row_u + ((width + 63) & ~63) / 2; 568 569 for (y = 0; y < height; ++y) { 570 ARGBToUV422Row(src_argb, row_u, row_v, width); 571 ARGBToYRow(src_argb, row_y, width); 572 I422ToYUY2Row(row_y, row_u, row_v, dst_yuy2, width); 573 src_argb += src_stride_argb; 574 dst_yuy2 += dst_stride_yuy2; 575 } 576 577 free_aligned_buffer_64(row_y); 578 } 579 return 0; 580 } 581 582 // Convert ARGB to UYVY. 583 LIBYUV_API 584 int ARGBToUYVY(const uint8* src_argb, int src_stride_argb, 585 uint8* dst_uyvy, int dst_stride_uyvy, 586 int width, int height) { 587 int y; 588 void (*ARGBToUV422Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v, 589 int pix) = ARGBToUV422Row_C; 590 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = 591 ARGBToYRow_C; 592 void (*I422ToUYVYRow)(const uint8* src_y, const uint8* src_u, 593 const uint8* src_v, uint8* dst_uyvy, int width) = I422ToUYVYRow_C; 594 595 if (!src_argb || !dst_uyvy || 596 width <= 0 || height == 0) { 597 return -1; 598 } 599 // Negative height means invert the image. 600 if (height < 0) { 601 height = -height; 602 dst_uyvy = dst_uyvy + (height - 1) * dst_stride_uyvy; 603 dst_stride_uyvy = -dst_stride_uyvy; 604 } 605 // Coalesce rows. 606 if (src_stride_argb == width * 4 && 607 dst_stride_uyvy == width * 2) { 608 width *= height; 609 height = 1; 610 src_stride_argb = dst_stride_uyvy = 0; 611 } 612 #if defined(HAS_ARGBTOUV422ROW_SSSE3) 613 if (TestCpuFlag(kCpuHasSSSE3)) { 614 ARGBToUV422Row = ARGBToUV422Row_Any_SSSE3; 615 if (IS_ALIGNED(width, 16)) { 616 ARGBToUV422Row = ARGBToUV422Row_SSSE3; 617 } 618 } 619 #endif 620 #if defined(HAS_ARGBTOUV422ROW_NEON) 621 if (TestCpuFlag(kCpuHasNEON)) { 622 ARGBToUV422Row = ARGBToUV422Row_Any_NEON; 623 if (IS_ALIGNED(width, 16)) { 624 ARGBToUV422Row = ARGBToUV422Row_NEON; 625 } 626 } 627 #endif 628 #if defined(HAS_ARGBTOYROW_SSSE3) 629 if (TestCpuFlag(kCpuHasSSSE3)) { 630 ARGBToYRow = ARGBToYRow_Any_SSSE3; 631 if (IS_ALIGNED(width, 16)) { 632 ARGBToYRow = ARGBToYRow_SSSE3; 633 } 634 } 635 #endif 636 #if defined(HAS_ARGBTOYROW_AVX2) 637 if (TestCpuFlag(kCpuHasAVX2)) { 638 ARGBToYRow = ARGBToYRow_Any_AVX2; 639 if (IS_ALIGNED(width, 32)) { 640 ARGBToYRow = ARGBToYRow_AVX2; 641 } 642 } 643 #endif 644 #if defined(HAS_ARGBTOYROW_NEON) 645 if (TestCpuFlag(kCpuHasNEON)) { 646 ARGBToYRow = ARGBToYRow_Any_NEON; 647 if (IS_ALIGNED(width, 8)) { 648 ARGBToYRow = ARGBToYRow_NEON; 649 } 650 } 651 #endif 652 653 #if defined(HAS_I422TOUYVYROW_SSE2) 654 if (TestCpuFlag(kCpuHasSSE2)) { 655 I422ToUYVYRow = I422ToUYVYRow_Any_SSE2; 656 if (IS_ALIGNED(width, 16)) { 657 I422ToUYVYRow = I422ToUYVYRow_SSE2; 658 } 659 } 660 #endif 661 #if defined(HAS_I422TOUYVYROW_NEON) 662 if (TestCpuFlag(kCpuHasNEON)) { 663 I422ToUYVYRow = I422ToUYVYRow_Any_NEON; 664 if (IS_ALIGNED(width, 16)) { 665 I422ToUYVYRow = I422ToUYVYRow_NEON; 666 } 667 } 668 #endif 669 670 { 671 // Allocate a rows of yuv. 672 align_buffer_64(row_y, ((width + 63) & ~63) * 2); 673 uint8* row_u = row_y + ((width + 63) & ~63); 674 uint8* row_v = row_u + ((width + 63) & ~63) / 2; 675 676 for (y = 0; y < height; ++y) { 677 ARGBToUV422Row(src_argb, row_u, row_v, width); 678 ARGBToYRow(src_argb, row_y, width); 679 I422ToUYVYRow(row_y, row_u, row_v, dst_uyvy, width); 680 src_argb += src_stride_argb; 681 dst_uyvy += dst_stride_uyvy; 682 } 683 684 free_aligned_buffer_64(row_y); 685 } 686 return 0; 687 } 688 689 // Convert ARGB to I400. 690 LIBYUV_API 691 int ARGBToI400(const uint8* src_argb, int src_stride_argb, 692 uint8* dst_y, int dst_stride_y, 693 int width, int height) { 694 int y; 695 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = 696 ARGBToYRow_C; 697 if (!src_argb || !dst_y || width <= 0 || height == 0) { 698 return -1; 699 } 700 if (height < 0) { 701 height = -height; 702 src_argb = src_argb + (height - 1) * src_stride_argb; 703 src_stride_argb = -src_stride_argb; 704 } 705 // Coalesce rows. 706 if (src_stride_argb == width * 4 && 707 dst_stride_y == width) { 708 width *= height; 709 height = 1; 710 src_stride_argb = dst_stride_y = 0; 711 } 712 #if defined(HAS_ARGBTOYROW_SSSE3) 713 if (TestCpuFlag(kCpuHasSSSE3)) { 714 ARGBToYRow = ARGBToYRow_Any_SSSE3; 715 if (IS_ALIGNED(width, 16)) { 716 ARGBToYRow = ARGBToYRow_SSSE3; 717 } 718 } 719 #endif 720 #if defined(HAS_ARGBTOYROW_AVX2) 721 if (TestCpuFlag(kCpuHasAVX2)) { 722 ARGBToYRow = ARGBToYRow_Any_AVX2; 723 if (IS_ALIGNED(width, 32)) { 724 ARGBToYRow = ARGBToYRow_AVX2; 725 } 726 } 727 #endif 728 #if defined(HAS_ARGBTOYROW_NEON) 729 if (TestCpuFlag(kCpuHasNEON)) { 730 ARGBToYRow = ARGBToYRow_Any_NEON; 731 if (IS_ALIGNED(width, 8)) { 732 ARGBToYRow = ARGBToYRow_NEON; 733 } 734 } 735 #endif 736 737 for (y = 0; y < height; ++y) { 738 ARGBToYRow(src_argb, dst_y, width); 739 src_argb += src_stride_argb; 740 dst_y += dst_stride_y; 741 } 742 return 0; 743 } 744 745 // Shuffle table for converting ARGB to RGBA. 746 static uvec8 kShuffleMaskARGBToRGBA = { 747 3u, 0u, 1u, 2u, 7u, 4u, 5u, 6u, 11u, 8u, 9u, 10u, 15u, 12u, 13u, 14u 748 }; 749 750 // Convert ARGB to RGBA. 751 LIBYUV_API 752 int ARGBToRGBA(const uint8* src_argb, int src_stride_argb, 753 uint8* dst_rgba, int dst_stride_rgba, 754 int width, int height) { 755 return ARGBShuffle(src_argb, src_stride_argb, 756 dst_rgba, dst_stride_rgba, 757 (const uint8*)(&kShuffleMaskARGBToRGBA), 758 width, height); 759 } 760 761 // Convert ARGB To RGB24. 762 LIBYUV_API 763 int ARGBToRGB24(const uint8* src_argb, int src_stride_argb, 764 uint8* dst_rgb24, int dst_stride_rgb24, 765 int width, int height) { 766 int y; 767 void (*ARGBToRGB24Row)(const uint8* src_argb, uint8* dst_rgb, int pix) = 768 ARGBToRGB24Row_C; 769 if (!src_argb || !dst_rgb24 || width <= 0 || height == 0) { 770 return -1; 771 } 772 if (height < 0) { 773 height = -height; 774 src_argb = src_argb + (height - 1) * src_stride_argb; 775 src_stride_argb = -src_stride_argb; 776 } 777 // Coalesce rows. 778 if (src_stride_argb == width * 4 && 779 dst_stride_rgb24 == width * 3) { 780 width *= height; 781 height = 1; 782 src_stride_argb = dst_stride_rgb24 = 0; 783 } 784 #if defined(HAS_ARGBTORGB24ROW_SSSE3) 785 if (TestCpuFlag(kCpuHasSSSE3)) { 786 ARGBToRGB24Row = ARGBToRGB24Row_Any_SSSE3; 787 if (IS_ALIGNED(width, 16)) { 788 ARGBToRGB24Row = ARGBToRGB24Row_SSSE3; 789 } 790 } 791 #endif 792 #if defined(HAS_ARGBTORGB24ROW_NEON) 793 if (TestCpuFlag(kCpuHasNEON)) { 794 ARGBToRGB24Row = ARGBToRGB24Row_Any_NEON; 795 if (IS_ALIGNED(width, 8)) { 796 ARGBToRGB24Row = ARGBToRGB24Row_NEON; 797 } 798 } 799 #endif 800 801 for (y = 0; y < height; ++y) { 802 ARGBToRGB24Row(src_argb, dst_rgb24, width); 803 src_argb += src_stride_argb; 804 dst_rgb24 += dst_stride_rgb24; 805 } 806 return 0; 807 } 808 809 // Convert ARGB To RAW. 810 LIBYUV_API 811 int ARGBToRAW(const uint8* src_argb, int src_stride_argb, 812 uint8* dst_raw, int dst_stride_raw, 813 int width, int height) { 814 int y; 815 void (*ARGBToRAWRow)(const uint8* src_argb, uint8* dst_rgb, int pix) = 816 ARGBToRAWRow_C; 817 if (!src_argb || !dst_raw || width <= 0 || height == 0) { 818 return -1; 819 } 820 if (height < 0) { 821 height = -height; 822 src_argb = src_argb + (height - 1) * src_stride_argb; 823 src_stride_argb = -src_stride_argb; 824 } 825 // Coalesce rows. 826 if (src_stride_argb == width * 4 && 827 dst_stride_raw == width * 3) { 828 width *= height; 829 height = 1; 830 src_stride_argb = dst_stride_raw = 0; 831 } 832 #if defined(HAS_ARGBTORAWROW_SSSE3) 833 if (TestCpuFlag(kCpuHasSSSE3)) { 834 ARGBToRAWRow = ARGBToRAWRow_Any_SSSE3; 835 if (IS_ALIGNED(width, 16)) { 836 ARGBToRAWRow = ARGBToRAWRow_SSSE3; 837 } 838 } 839 #endif 840 #if defined(HAS_ARGBTORAWROW_NEON) 841 if (TestCpuFlag(kCpuHasNEON)) { 842 ARGBToRAWRow = ARGBToRAWRow_Any_NEON; 843 if (IS_ALIGNED(width, 8)) { 844 ARGBToRAWRow = ARGBToRAWRow_NEON; 845 } 846 } 847 #endif 848 849 for (y = 0; y < height; ++y) { 850 ARGBToRAWRow(src_argb, dst_raw, width); 851 src_argb += src_stride_argb; 852 dst_raw += dst_stride_raw; 853 } 854 return 0; 855 } 856 857 // Ordered 8x8 dither for 888 to 565. Values from 0 to 7. 858 static const uint8 kDither565_4x4[16] = { 859 0, 4, 1, 5, 860 6, 2, 7, 3, 861 1, 5, 0, 4, 862 7, 3, 6, 2, 863 }; 864 865 // Convert ARGB To RGB565 with 4x4 dither matrix (16 bytes). 866 LIBYUV_API 867 int ARGBToRGB565Dither(const uint8* src_argb, int src_stride_argb, 868 uint8* dst_rgb565, int dst_stride_rgb565, 869 const uint8* dither4x4, int width, int height) { 870 int y; 871 void (*ARGBToRGB565DitherRow)(const uint8* src_argb, uint8* dst_rgb, 872 const uint32 dither4, int pix) = ARGBToRGB565DitherRow_C; 873 if (!src_argb || !dst_rgb565 || width <= 0 || height == 0) { 874 return -1; 875 } 876 if (height < 0) { 877 height = -height; 878 src_argb = src_argb + (height - 1) * src_stride_argb; 879 src_stride_argb = -src_stride_argb; 880 } 881 if (!dither4x4) { 882 dither4x4 = kDither565_4x4; 883 } 884 #if defined(HAS_ARGBTORGB565DITHERROW_SSE2) 885 if (TestCpuFlag(kCpuHasSSE2)) { 886 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_SSE2; 887 if (IS_ALIGNED(width, 4)) { 888 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_SSE2; 889 } 890 } 891 #endif 892 #if defined(HAS_ARGBTORGB565DITHERROW_AVX2) 893 if (TestCpuFlag(kCpuHasAVX2)) { 894 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_AVX2; 895 if (IS_ALIGNED(width, 8)) { 896 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_AVX2; 897 } 898 } 899 #endif 900 #if defined(HAS_ARGBTORGB565DITHERROW_NEON) 901 if (TestCpuFlag(kCpuHasNEON)) { 902 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_Any_NEON; 903 if (IS_ALIGNED(width, 8)) { 904 ARGBToRGB565DitherRow = ARGBToRGB565DitherRow_NEON; 905 } 906 } 907 #endif 908 for (y = 0; y < height; ++y) { 909 ARGBToRGB565DitherRow(src_argb, dst_rgb565, 910 *(uint32*)(dither4x4 + ((y & 3) << 2)), width); 911 src_argb += src_stride_argb; 912 dst_rgb565 += dst_stride_rgb565; 913 } 914 return 0; 915 } 916 917 // Convert ARGB To RGB565. 918 // TODO(fbarchard): Consider using dither function low level with zeros. 919 LIBYUV_API 920 int ARGBToRGB565(const uint8* src_argb, int src_stride_argb, 921 uint8* dst_rgb565, int dst_stride_rgb565, 922 int width, int height) { 923 int y; 924 void (*ARGBToRGB565Row)(const uint8* src_argb, uint8* dst_rgb, int pix) = 925 ARGBToRGB565Row_C; 926 if (!src_argb || !dst_rgb565 || width <= 0 || height == 0) { 927 return -1; 928 } 929 if (height < 0) { 930 height = -height; 931 src_argb = src_argb + (height - 1) * src_stride_argb; 932 src_stride_argb = -src_stride_argb; 933 } 934 // Coalesce rows. 935 if (src_stride_argb == width * 4 && 936 dst_stride_rgb565 == width * 2) { 937 width *= height; 938 height = 1; 939 src_stride_argb = dst_stride_rgb565 = 0; 940 } 941 #if defined(HAS_ARGBTORGB565ROW_SSE2) 942 if (TestCpuFlag(kCpuHasSSE2)) { 943 ARGBToRGB565Row = ARGBToRGB565Row_Any_SSE2; 944 if (IS_ALIGNED(width, 4)) { 945 ARGBToRGB565Row = ARGBToRGB565Row_SSE2; 946 } 947 } 948 #endif 949 #if defined(HAS_ARGBTORGB565ROW_AVX2) 950 if (TestCpuFlag(kCpuHasAVX2)) { 951 ARGBToRGB565Row = ARGBToRGB565Row_Any_AVX2; 952 if (IS_ALIGNED(width, 8)) { 953 ARGBToRGB565Row = ARGBToRGB565Row_AVX2; 954 } 955 } 956 #endif 957 #if defined(HAS_ARGBTORGB565ROW_NEON) 958 if (TestCpuFlag(kCpuHasNEON)) { 959 ARGBToRGB565Row = ARGBToRGB565Row_Any_NEON; 960 if (IS_ALIGNED(width, 8)) { 961 ARGBToRGB565Row = ARGBToRGB565Row_NEON; 962 } 963 } 964 #endif 965 966 for (y = 0; y < height; ++y) { 967 ARGBToRGB565Row(src_argb, dst_rgb565, width); 968 src_argb += src_stride_argb; 969 dst_rgb565 += dst_stride_rgb565; 970 } 971 return 0; 972 } 973 974 // Convert ARGB To ARGB1555. 975 LIBYUV_API 976 int ARGBToARGB1555(const uint8* src_argb, int src_stride_argb, 977 uint8* dst_argb1555, int dst_stride_argb1555, 978 int width, int height) { 979 int y; 980 void (*ARGBToARGB1555Row)(const uint8* src_argb, uint8* dst_rgb, int pix) = 981 ARGBToARGB1555Row_C; 982 if (!src_argb || !dst_argb1555 || width <= 0 || height == 0) { 983 return -1; 984 } 985 if (height < 0) { 986 height = -height; 987 src_argb = src_argb + (height - 1) * src_stride_argb; 988 src_stride_argb = -src_stride_argb; 989 } 990 // Coalesce rows. 991 if (src_stride_argb == width * 4 && 992 dst_stride_argb1555 == width * 2) { 993 width *= height; 994 height = 1; 995 src_stride_argb = dst_stride_argb1555 = 0; 996 } 997 #if defined(HAS_ARGBTOARGB1555ROW_SSE2) 998 if (TestCpuFlag(kCpuHasSSE2)) { 999 ARGBToARGB1555Row = ARGBToARGB1555Row_Any_SSE2; 1000 if (IS_ALIGNED(width, 4)) { 1001 ARGBToARGB1555Row = ARGBToARGB1555Row_SSE2; 1002 } 1003 } 1004 #endif 1005 #if defined(HAS_ARGBTOARGB1555ROW_AVX2) 1006 if (TestCpuFlag(kCpuHasAVX2)) { 1007 ARGBToARGB1555Row = ARGBToARGB1555Row_Any_AVX2; 1008 if (IS_ALIGNED(width, 8)) { 1009 ARGBToARGB1555Row = ARGBToARGB1555Row_AVX2; 1010 } 1011 } 1012 #endif 1013 #if defined(HAS_ARGBTOARGB1555ROW_NEON) 1014 if (TestCpuFlag(kCpuHasNEON)) { 1015 ARGBToARGB1555Row = ARGBToARGB1555Row_Any_NEON; 1016 if (IS_ALIGNED(width, 8)) { 1017 ARGBToARGB1555Row = ARGBToARGB1555Row_NEON; 1018 } 1019 } 1020 #endif 1021 1022 for (y = 0; y < height; ++y) { 1023 ARGBToARGB1555Row(src_argb, dst_argb1555, width); 1024 src_argb += src_stride_argb; 1025 dst_argb1555 += dst_stride_argb1555; 1026 } 1027 return 0; 1028 } 1029 1030 // Convert ARGB To ARGB4444. 1031 LIBYUV_API 1032 int ARGBToARGB4444(const uint8* src_argb, int src_stride_argb, 1033 uint8* dst_argb4444, int dst_stride_argb4444, 1034 int width, int height) { 1035 int y; 1036 void (*ARGBToARGB4444Row)(const uint8* src_argb, uint8* dst_rgb, int pix) = 1037 ARGBToARGB4444Row_C; 1038 if (!src_argb || !dst_argb4444 || width <= 0 || height == 0) { 1039 return -1; 1040 } 1041 if (height < 0) { 1042 height = -height; 1043 src_argb = src_argb + (height - 1) * src_stride_argb; 1044 src_stride_argb = -src_stride_argb; 1045 } 1046 // Coalesce rows. 1047 if (src_stride_argb == width * 4 && 1048 dst_stride_argb4444 == width * 2) { 1049 width *= height; 1050 height = 1; 1051 src_stride_argb = dst_stride_argb4444 = 0; 1052 } 1053 #if defined(HAS_ARGBTOARGB4444ROW_SSE2) 1054 if (TestCpuFlag(kCpuHasSSE2)) { 1055 ARGBToARGB4444Row = ARGBToARGB4444Row_Any_SSE2; 1056 if (IS_ALIGNED(width, 4)) { 1057 ARGBToARGB4444Row = ARGBToARGB4444Row_SSE2; 1058 } 1059 } 1060 #endif 1061 #if defined(HAS_ARGBTOARGB4444ROW_AVX2) 1062 if (TestCpuFlag(kCpuHasAVX2)) { 1063 ARGBToARGB4444Row = ARGBToARGB4444Row_Any_AVX2; 1064 if (IS_ALIGNED(width, 8)) { 1065 ARGBToARGB4444Row = ARGBToARGB4444Row_AVX2; 1066 } 1067 } 1068 #endif 1069 #if defined(HAS_ARGBTOARGB4444ROW_NEON) 1070 if (TestCpuFlag(kCpuHasNEON)) { 1071 ARGBToARGB4444Row = ARGBToARGB4444Row_Any_NEON; 1072 if (IS_ALIGNED(width, 8)) { 1073 ARGBToARGB4444Row = ARGBToARGB4444Row_NEON; 1074 } 1075 } 1076 #endif 1077 1078 for (y = 0; y < height; ++y) { 1079 ARGBToARGB4444Row(src_argb, dst_argb4444, width); 1080 src_argb += src_stride_argb; 1081 dst_argb4444 += dst_stride_argb4444; 1082 } 1083 return 0; 1084 } 1085 1086 // Convert ARGB to J420. (JPeg full range I420). 1087 LIBYUV_API 1088 int ARGBToJ420(const uint8* src_argb, int src_stride_argb, 1089 uint8* dst_yj, int dst_stride_yj, 1090 uint8* dst_u, int dst_stride_u, 1091 uint8* dst_v, int dst_stride_v, 1092 int width, int height) { 1093 int y; 1094 void (*ARGBToUVJRow)(const uint8* src_argb0, int src_stride_argb, 1095 uint8* dst_u, uint8* dst_v, int width) = ARGBToUVJRow_C; 1096 void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_yj, int pix) = 1097 ARGBToYJRow_C; 1098 if (!src_argb || 1099 !dst_yj || !dst_u || !dst_v || 1100 width <= 0 || height == 0) { 1101 return -1; 1102 } 1103 // Negative height means invert the image. 1104 if (height < 0) { 1105 height = -height; 1106 src_argb = src_argb + (height - 1) * src_stride_argb; 1107 src_stride_argb = -src_stride_argb; 1108 } 1109 #if defined(HAS_ARGBTOYJROW_SSSE3) && defined(HAS_ARGBTOUVJROW_SSSE3) 1110 if (TestCpuFlag(kCpuHasSSSE3)) { 1111 ARGBToUVJRow = ARGBToUVJRow_Any_SSSE3; 1112 ARGBToYJRow = ARGBToYJRow_Any_SSSE3; 1113 if (IS_ALIGNED(width, 16)) { 1114 ARGBToUVJRow = ARGBToUVJRow_SSSE3; 1115 ARGBToYJRow = ARGBToYJRow_SSSE3; 1116 } 1117 } 1118 #endif 1119 #if defined(HAS_ARGBTOYJROW_AVX2) 1120 if (TestCpuFlag(kCpuHasAVX2)) { 1121 ARGBToYJRow = ARGBToYJRow_Any_AVX2; 1122 if (IS_ALIGNED(width, 32)) { 1123 ARGBToYJRow = ARGBToYJRow_AVX2; 1124 } 1125 } 1126 #endif 1127 #if defined(HAS_ARGBTOYJROW_NEON) 1128 if (TestCpuFlag(kCpuHasNEON)) { 1129 ARGBToYJRow = ARGBToYJRow_Any_NEON; 1130 if (IS_ALIGNED(width, 8)) { 1131 ARGBToYJRow = ARGBToYJRow_NEON; 1132 } 1133 } 1134 #endif 1135 #if defined(HAS_ARGBTOUVJROW_NEON) 1136 if (TestCpuFlag(kCpuHasNEON)) { 1137 ARGBToUVJRow = ARGBToUVJRow_Any_NEON; 1138 if (IS_ALIGNED(width, 16)) { 1139 ARGBToUVJRow = ARGBToUVJRow_NEON; 1140 } 1141 } 1142 #endif 1143 1144 for (y = 0; y < height - 1; y += 2) { 1145 ARGBToUVJRow(src_argb, src_stride_argb, dst_u, dst_v, width); 1146 ARGBToYJRow(src_argb, dst_yj, width); 1147 ARGBToYJRow(src_argb + src_stride_argb, dst_yj + dst_stride_yj, width); 1148 src_argb += src_stride_argb * 2; 1149 dst_yj += dst_stride_yj * 2; 1150 dst_u += dst_stride_u; 1151 dst_v += dst_stride_v; 1152 } 1153 if (height & 1) { 1154 ARGBToUVJRow(src_argb, 0, dst_u, dst_v, width); 1155 ARGBToYJRow(src_argb, dst_yj, width); 1156 } 1157 return 0; 1158 } 1159 1160 // ARGB little endian (bgra in memory) to J422 1161 LIBYUV_API 1162 int ARGBToJ422(const uint8* src_argb, int src_stride_argb, 1163 uint8* dst_y, int dst_stride_y, 1164 uint8* dst_u, int dst_stride_u, 1165 uint8* dst_v, int dst_stride_v, 1166 int width, int height) { 1167 int y; 1168 void (*ARGBToUVJ422Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v, 1169 int pix) = ARGBToUVJ422Row_C; 1170 void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_y, int pix) = 1171 ARGBToYJRow_C; 1172 if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) { 1173 return -1; 1174 } 1175 if (height < 0) { 1176 height = -height; 1177 src_argb = src_argb + (height - 1) * src_stride_argb; 1178 src_stride_argb = -src_stride_argb; 1179 } 1180 // Coalesce rows. 1181 if (src_stride_argb == width * 4 && 1182 dst_stride_y == width && 1183 dst_stride_u * 2 == width && 1184 dst_stride_v * 2 == width) { 1185 width *= height; 1186 height = 1; 1187 src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0; 1188 } 1189 #if defined(HAS_ARGBTOUVJ422ROW_SSSE3) 1190 if (TestCpuFlag(kCpuHasSSSE3)) { 1191 ARGBToUVJ422Row = ARGBToUVJ422Row_Any_SSSE3; 1192 if (IS_ALIGNED(width, 16)) { 1193 ARGBToUVJ422Row = ARGBToUVJ422Row_SSSE3; 1194 } 1195 } 1196 #endif 1197 #if defined(HAS_ARGBTOUVJ422ROW_NEON) 1198 if (TestCpuFlag(kCpuHasNEON)) { 1199 ARGBToUVJ422Row = ARGBToUVJ422Row_Any_NEON; 1200 if (IS_ALIGNED(width, 16)) { 1201 ARGBToUVJ422Row = ARGBToUVJ422Row_NEON; 1202 } 1203 } 1204 #endif 1205 1206 #if defined(HAS_ARGBTOYJROW_SSSE3) 1207 if (TestCpuFlag(kCpuHasSSSE3)) { 1208 ARGBToYJRow = ARGBToYJRow_Any_SSSE3; 1209 if (IS_ALIGNED(width, 16)) { 1210 ARGBToYJRow = ARGBToYJRow_SSSE3; 1211 } 1212 } 1213 #endif 1214 #if defined(HAS_ARGBTOYJROW_AVX2) 1215 if (TestCpuFlag(kCpuHasAVX2)) { 1216 ARGBToYJRow = ARGBToYJRow_Any_AVX2; 1217 if (IS_ALIGNED(width, 32)) { 1218 ARGBToYJRow = ARGBToYJRow_AVX2; 1219 } 1220 } 1221 #endif 1222 #if defined(HAS_ARGBTOYJROW_NEON) 1223 if (TestCpuFlag(kCpuHasNEON)) { 1224 ARGBToYJRow = ARGBToYJRow_Any_NEON; 1225 if (IS_ALIGNED(width, 8)) { 1226 ARGBToYJRow = ARGBToYJRow_NEON; 1227 } 1228 } 1229 #endif 1230 1231 for (y = 0; y < height; ++y) { 1232 ARGBToUVJ422Row(src_argb, dst_u, dst_v, width); 1233 ARGBToYJRow(src_argb, dst_y, width); 1234 src_argb += src_stride_argb; 1235 dst_y += dst_stride_y; 1236 dst_u += dst_stride_u; 1237 dst_v += dst_stride_v; 1238 } 1239 return 0; 1240 } 1241 1242 // Convert ARGB to J400. 1243 LIBYUV_API 1244 int ARGBToJ400(const uint8* src_argb, int src_stride_argb, 1245 uint8* dst_yj, int dst_stride_yj, 1246 int width, int height) { 1247 int y; 1248 void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_yj, int pix) = 1249 ARGBToYJRow_C; 1250 if (!src_argb || !dst_yj || width <= 0 || height == 0) { 1251 return -1; 1252 } 1253 if (height < 0) { 1254 height = -height; 1255 src_argb = src_argb + (height - 1) * src_stride_argb; 1256 src_stride_argb = -src_stride_argb; 1257 } 1258 // Coalesce rows. 1259 if (src_stride_argb == width * 4 && 1260 dst_stride_yj == width) { 1261 width *= height; 1262 height = 1; 1263 src_stride_argb = dst_stride_yj = 0; 1264 } 1265 #if defined(HAS_ARGBTOYJROW_SSSE3) 1266 if (TestCpuFlag(kCpuHasSSSE3)) { 1267 ARGBToYJRow = ARGBToYJRow_Any_SSSE3; 1268 if (IS_ALIGNED(width, 16)) { 1269 ARGBToYJRow = ARGBToYJRow_SSSE3; 1270 } 1271 } 1272 #endif 1273 #if defined(HAS_ARGBTOYJROW_AVX2) 1274 if (TestCpuFlag(kCpuHasAVX2)) { 1275 ARGBToYJRow = ARGBToYJRow_Any_AVX2; 1276 if (IS_ALIGNED(width, 32)) { 1277 ARGBToYJRow = ARGBToYJRow_AVX2; 1278 } 1279 } 1280 #endif 1281 #if defined(HAS_ARGBTOYJROW_NEON) 1282 if (TestCpuFlag(kCpuHasNEON)) { 1283 ARGBToYJRow = ARGBToYJRow_Any_NEON; 1284 if (IS_ALIGNED(width, 8)) { 1285 ARGBToYJRow = ARGBToYJRow_NEON; 1286 } 1287 } 1288 #endif 1289 1290 for (y = 0; y < height; ++y) { 1291 ARGBToYJRow(src_argb, dst_yj, width); 1292 src_argb += src_stride_argb; 1293 dst_yj += dst_stride_yj; 1294 } 1295 return 0; 1296 } 1297 1298 #ifdef __cplusplus 1299 } // extern "C" 1300 } // namespace libyuv 1301 #endif 1302