media/libyuv/source/convert_from_argb.cc

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial