media/libyuv/source/convert.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 2011 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.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/planar_functions.h"
michael@0 16 #include "libyuv/rotate.h"
michael@0 17 #include "libyuv/scale.h" // For ScalePlane()
michael@0 18 #include "libyuv/row.h"
michael@0 19
michael@0 20 #ifdef __cplusplus
michael@0 21 namespace libyuv {
michael@0 22 extern "C" {
michael@0 23 #endif
michael@0 24
michael@0 25 #define SUBSAMPLE(v, a, s) (v < 0) ? (-((-v + a) >> s)) : ((v + a) >> s)
michael@0 26 static __inline int Abs(int v) {
michael@0 27 return v >= 0 ? v : -v;
michael@0 28 }
michael@0 29
michael@0 30 // Any I4xx To I420 format with mirroring.
michael@0 31 static int I4xxToI420(const uint8* src_y, int src_stride_y,
michael@0 32 const uint8* src_u, int src_stride_u,
michael@0 33 const uint8* src_v, int src_stride_v,
michael@0 34 uint8* dst_y, int dst_stride_y,
michael@0 35 uint8* dst_u, int dst_stride_u,
michael@0 36 uint8* dst_v, int dst_stride_v,
michael@0 37 int src_y_width, int src_y_height,
michael@0 38 int src_uv_width, int src_uv_height) {
michael@0 39 if (src_y_width == 0 || src_y_height == 0 ||
michael@0 40 src_uv_width == 0 || src_uv_height == 0) {
michael@0 41 return -1;
michael@0 42 }
michael@0 43 const int dst_y_width = Abs(src_y_width);
michael@0 44 const int dst_y_height = Abs(src_y_height);
michael@0 45 const int dst_uv_width = SUBSAMPLE(dst_y_width, 1, 1);
michael@0 46 const int dst_uv_height = SUBSAMPLE(dst_y_height, 1, 1);
michael@0 47 ScalePlane(src_y, src_stride_y, src_y_width, src_y_height,
michael@0 48 dst_y, dst_stride_y, dst_y_width, dst_y_height,
michael@0 49 kFilterBilinear);
michael@0 50 ScalePlane(src_u, src_stride_u, src_uv_width, src_uv_height,
michael@0 51 dst_u, dst_stride_u, dst_uv_width, dst_uv_height,
michael@0 52 kFilterBilinear);
michael@0 53 ScalePlane(src_v, src_stride_v, src_uv_width, src_uv_height,
michael@0 54 dst_v, dst_stride_v, dst_uv_width, dst_uv_height,
michael@0 55 kFilterBilinear);
michael@0 56 return 0;
michael@0 57 }
michael@0 58
michael@0 59 // Copy I420 with optional flipping
michael@0 60 // TODO(fbarchard): Use Scale plane which supports mirroring, but ensure
michael@0 61 // is does row coalescing.
michael@0 62 LIBYUV_API
michael@0 63 int I420Copy(const uint8* src_y, int src_stride_y,
michael@0 64 const uint8* src_u, int src_stride_u,
michael@0 65 const uint8* src_v, int src_stride_v,
michael@0 66 uint8* dst_y, int dst_stride_y,
michael@0 67 uint8* dst_u, int dst_stride_u,
michael@0 68 uint8* dst_v, int dst_stride_v,
michael@0 69 int width, int height) {
michael@0 70 if (!src_y || !src_u || !src_v ||
michael@0 71 !dst_y || !dst_u || !dst_v ||
michael@0 72 width <= 0 || height == 0) {
michael@0 73 return -1;
michael@0 74 }
michael@0 75 // Negative height means invert the image.
michael@0 76 if (height < 0) {
michael@0 77 height = -height;
michael@0 78 const int halfheight = (height + 1) >> 1;
michael@0 79 src_y = src_y + (height - 1) * src_stride_y;
michael@0 80 src_u = src_u + (halfheight - 1) * src_stride_u;
michael@0 81 src_v = src_v + (halfheight - 1) * src_stride_v;
michael@0 82 src_stride_y = -src_stride_y;
michael@0 83 src_stride_u = -src_stride_u;
michael@0 84 src_stride_v = -src_stride_v;
michael@0 85 }
michael@0 86
michael@0 87 if (dst_y) {
michael@0 88 CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
michael@0 89 }
michael@0 90 // Copy UV planes.
michael@0 91 const int halfwidth = (width + 1) >> 1;
michael@0 92 const int halfheight = (height + 1) >> 1;
michael@0 93 CopyPlane(src_u, src_stride_u, dst_u, dst_stride_u, halfwidth, halfheight);
michael@0 94 CopyPlane(src_v, src_stride_v, dst_v, dst_stride_v, halfwidth, halfheight);
michael@0 95 return 0;
michael@0 96 }
michael@0 97
michael@0 98 // 422 chroma is 1/2 width, 1x height
michael@0 99 // 420 chroma is 1/2 width, 1/2 height
michael@0 100 LIBYUV_API
michael@0 101 int I422ToI420(const uint8* src_y, int src_stride_y,
michael@0 102 const uint8* src_u, int src_stride_u,
michael@0 103 const uint8* src_v, int src_stride_v,
michael@0 104 uint8* dst_y, int dst_stride_y,
michael@0 105 uint8* dst_u, int dst_stride_u,
michael@0 106 uint8* dst_v, int dst_stride_v,
michael@0 107 int width, int height) {
michael@0 108 const int src_uv_width = SUBSAMPLE(width, 1, 1);
michael@0 109 return I4xxToI420(src_y, src_stride_y,
michael@0 110 src_u, src_stride_u,
michael@0 111 src_v, src_stride_v,
michael@0 112 dst_y, dst_stride_y,
michael@0 113 dst_u, dst_stride_u,
michael@0 114 dst_v, dst_stride_v,
michael@0 115 width, height,
michael@0 116 src_uv_width, height);
michael@0 117 }
michael@0 118
michael@0 119 // 444 chroma is 1x width, 1x height
michael@0 120 // 420 chroma is 1/2 width, 1/2 height
michael@0 121 LIBYUV_API
michael@0 122 int I444ToI420(const uint8* src_y, int src_stride_y,
michael@0 123 const uint8* src_u, int src_stride_u,
michael@0 124 const uint8* src_v, int src_stride_v,
michael@0 125 uint8* dst_y, int dst_stride_y,
michael@0 126 uint8* dst_u, int dst_stride_u,
michael@0 127 uint8* dst_v, int dst_stride_v,
michael@0 128 int width, int height) {
michael@0 129 return I4xxToI420(src_y, src_stride_y,
michael@0 130 src_u, src_stride_u,
michael@0 131 src_v, src_stride_v,
michael@0 132 dst_y, dst_stride_y,
michael@0 133 dst_u, dst_stride_u,
michael@0 134 dst_v, dst_stride_v,
michael@0 135 width, height,
michael@0 136 width, height);
michael@0 137 }
michael@0 138
michael@0 139 // 411 chroma is 1/4 width, 1x height
michael@0 140 // 420 chroma is 1/2 width, 1/2 height
michael@0 141 LIBYUV_API
michael@0 142 int I411ToI420(const uint8* src_y, int src_stride_y,
michael@0 143 const uint8* src_u, int src_stride_u,
michael@0 144 const uint8* src_v, int src_stride_v,
michael@0 145 uint8* dst_y, int dst_stride_y,
michael@0 146 uint8* dst_u, int dst_stride_u,
michael@0 147 uint8* dst_v, int dst_stride_v,
michael@0 148 int width, int height) {
michael@0 149 const int src_uv_width = SUBSAMPLE(width, 3, 2);
michael@0 150 return I4xxToI420(src_y, src_stride_y,
michael@0 151 src_u, src_stride_u,
michael@0 152 src_v, src_stride_v,
michael@0 153 dst_y, dst_stride_y,
michael@0 154 dst_u, dst_stride_u,
michael@0 155 dst_v, dst_stride_v,
michael@0 156 width, height,
michael@0 157 src_uv_width, height);
michael@0 158 }
michael@0 159
michael@0 160 // I400 is greyscale typically used in MJPG
michael@0 161 LIBYUV_API
michael@0 162 int I400ToI420(const uint8* src_y, int src_stride_y,
michael@0 163 uint8* dst_y, int dst_stride_y,
michael@0 164 uint8* dst_u, int dst_stride_u,
michael@0 165 uint8* dst_v, int dst_stride_v,
michael@0 166 int width, int height) {
michael@0 167 if (!src_y || !dst_y || !dst_u || !dst_v ||
michael@0 168 width <= 0 || height == 0) {
michael@0 169 return -1;
michael@0 170 }
michael@0 171 // Negative height means invert the image.
michael@0 172 if (height < 0) {
michael@0 173 height = -height;
michael@0 174 src_y = src_y + (height - 1) * src_stride_y;
michael@0 175 src_stride_y = -src_stride_y;
michael@0 176 }
michael@0 177 int halfwidth = (width + 1) >> 1;
michael@0 178 int halfheight = (height + 1) >> 1;
michael@0 179 CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
michael@0 180 SetPlane(dst_u, dst_stride_u, halfwidth, halfheight, 128);
michael@0 181 SetPlane(dst_v, dst_stride_v, halfwidth, halfheight, 128);
michael@0 182 return 0;
michael@0 183 }
michael@0 184
michael@0 185 static void CopyPlane2(const uint8* src, int src_stride_0, int src_stride_1,
michael@0 186 uint8* dst, int dst_stride,
michael@0 187 int width, int height) {
michael@0 188 void (*CopyRow)(const uint8* src, uint8* dst, int width) = CopyRow_C;
michael@0 189 #if defined(HAS_COPYROW_X86)
michael@0 190 if (TestCpuFlag(kCpuHasX86) && IS_ALIGNED(width, 4)) {
michael@0 191 CopyRow = CopyRow_X86;
michael@0 192 }
michael@0 193 #endif
michael@0 194 #if defined(HAS_COPYROW_SSE2)
michael@0 195 if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 32) &&
michael@0 196 IS_ALIGNED(src, 16) &&
michael@0 197 IS_ALIGNED(src_stride_0, 16) && IS_ALIGNED(src_stride_1, 16) &&
michael@0 198 IS_ALIGNED(dst, 16) && IS_ALIGNED(dst_stride, 16)) {
michael@0 199 CopyRow = CopyRow_SSE2;
michael@0 200 }
michael@0 201 #endif
michael@0 202 #if defined(HAS_COPYROW_ERMS)
michael@0 203 if (TestCpuFlag(kCpuHasERMS)) {
michael@0 204 CopyRow = CopyRow_ERMS;
michael@0 205 }
michael@0 206 #endif
michael@0 207 #if defined(HAS_COPYROW_NEON)
michael@0 208 if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 32)) {
michael@0 209 CopyRow = CopyRow_NEON;
michael@0 210 }
michael@0 211 #endif
michael@0 212 #if defined(HAS_COPYROW_MIPS)
michael@0 213 if (TestCpuFlag(kCpuHasMIPS)) {
michael@0 214 CopyRow = CopyRow_MIPS;
michael@0 215 }
michael@0 216 #endif
michael@0 217
michael@0 218 // Copy plane
michael@0 219 for (int y = 0; y < height - 1; y += 2) {
michael@0 220 CopyRow(src, dst, width);
michael@0 221 CopyRow(src + src_stride_0, dst + dst_stride, width);
michael@0 222 src += src_stride_0 + src_stride_1;
michael@0 223 dst += dst_stride * 2;
michael@0 224 }
michael@0 225 if (height & 1) {
michael@0 226 CopyRow(src, dst, width);
michael@0 227 }
michael@0 228 }
michael@0 229
michael@0 230 // Support converting from FOURCC_M420
michael@0 231 // Useful for bandwidth constrained transports like USB 1.0 and 2.0 and for
michael@0 232 // easy conversion to I420.
michael@0 233 // M420 format description:
michael@0 234 // M420 is row biplanar 420: 2 rows of Y and 1 row of UV.
michael@0 235 // Chroma is half width / half height. (420)
michael@0 236 // src_stride_m420 is row planar. Normally this will be the width in pixels.
michael@0 237 // The UV plane is half width, but 2 values, so src_stride_m420 applies to
michael@0 238 // this as well as the two Y planes.
michael@0 239 static int X420ToI420(const uint8* src_y,
michael@0 240 int src_stride_y0, int src_stride_y1,
michael@0 241 const uint8* src_uv, int src_stride_uv,
michael@0 242 uint8* dst_y, int dst_stride_y,
michael@0 243 uint8* dst_u, int dst_stride_u,
michael@0 244 uint8* dst_v, int dst_stride_v,
michael@0 245 int width, int height) {
michael@0 246 if (!src_y || !src_uv ||
michael@0 247 !dst_y || !dst_u || !dst_v ||
michael@0 248 width <= 0 || height == 0) {
michael@0 249 return -1;
michael@0 250 }
michael@0 251 // Negative height means invert the image.
michael@0 252 if (height < 0) {
michael@0 253 height = -height;
michael@0 254 int halfheight = (height + 1) >> 1;
michael@0 255 dst_y = dst_y + (height - 1) * dst_stride_y;
michael@0 256 dst_u = dst_u + (halfheight - 1) * dst_stride_u;
michael@0 257 dst_v = dst_v + (halfheight - 1) * dst_stride_v;
michael@0 258 dst_stride_y = -dst_stride_y;
michael@0 259 dst_stride_u = -dst_stride_u;
michael@0 260 dst_stride_v = -dst_stride_v;
michael@0 261 }
michael@0 262 // Coalesce rows.
michael@0 263 int halfwidth = (width + 1) >> 1;
michael@0 264 int halfheight = (height + 1) >> 1;
michael@0 265 if (src_stride_y0 == width &&
michael@0 266 src_stride_y1 == width &&
michael@0 267 dst_stride_y == width) {
michael@0 268 width *= height;
michael@0 269 height = 1;
michael@0 270 src_stride_y0 = src_stride_y1 = dst_stride_y = 0;
michael@0 271 }
michael@0 272 // Coalesce rows.
michael@0 273 if (src_stride_uv == halfwidth * 2 &&
michael@0 274 dst_stride_u == halfwidth &&
michael@0 275 dst_stride_v == halfwidth) {
michael@0 276 halfwidth *= halfheight;
michael@0 277 halfheight = 1;
michael@0 278 src_stride_uv = dst_stride_u = dst_stride_v = 0;
michael@0 279 }
michael@0 280 void (*SplitUVRow)(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int pix) =
michael@0 281 SplitUVRow_C;
michael@0 282 #if defined(HAS_SPLITUVROW_SSE2)
michael@0 283 if (TestCpuFlag(kCpuHasSSE2) && halfwidth >= 16) {
michael@0 284 SplitUVRow = SplitUVRow_Any_SSE2;
michael@0 285 if (IS_ALIGNED(halfwidth, 16)) {
michael@0 286 SplitUVRow = SplitUVRow_Unaligned_SSE2;
michael@0 287 if (IS_ALIGNED(src_uv, 16) && IS_ALIGNED(src_stride_uv, 16) &&
michael@0 288 IS_ALIGNED(dst_u, 16) && IS_ALIGNED(dst_stride_u, 16) &&
michael@0 289 IS_ALIGNED(dst_v, 16) && IS_ALIGNED(dst_stride_v, 16)) {
michael@0 290 SplitUVRow = SplitUVRow_SSE2;
michael@0 291 }
michael@0 292 }
michael@0 293 }
michael@0 294 #endif
michael@0 295 #if defined(HAS_SPLITUVROW_AVX2)
michael@0 296 if (TestCpuFlag(kCpuHasAVX2) && halfwidth >= 32) {
michael@0 297 SplitUVRow = SplitUVRow_Any_AVX2;
michael@0 298 if (IS_ALIGNED(halfwidth, 32)) {
michael@0 299 SplitUVRow = SplitUVRow_AVX2;
michael@0 300 }
michael@0 301 }
michael@0 302 #endif
michael@0 303 #if defined(HAS_SPLITUVROW_NEON)
michael@0 304 if (TestCpuFlag(kCpuHasNEON) && halfwidth >= 16) {
michael@0 305 SplitUVRow = SplitUVRow_Any_NEON;
michael@0 306 if (IS_ALIGNED(halfwidth, 16)) {
michael@0 307 SplitUVRow = SplitUVRow_NEON;
michael@0 308 }
michael@0 309 }
michael@0 310 #endif
michael@0 311 #if defined(HAS_SPLITUVROW_MIPS_DSPR2)
michael@0 312 if (TestCpuFlag(kCpuHasMIPS_DSPR2) && halfwidth >= 16) {
michael@0 313 SplitUVRow = SplitUVRow_Any_MIPS_DSPR2;
michael@0 314 if (IS_ALIGNED(halfwidth, 16)) {
michael@0 315 SplitUVRow = SplitUVRow_Unaligned_MIPS_DSPR2;
michael@0 316 if (IS_ALIGNED(src_uv, 4) && IS_ALIGNED(src_stride_uv, 4) &&
michael@0 317 IS_ALIGNED(dst_u, 4) && IS_ALIGNED(dst_stride_u, 4) &&
michael@0 318 IS_ALIGNED(dst_v, 4) && IS_ALIGNED(dst_stride_v, 4)) {
michael@0 319 SplitUVRow = SplitUVRow_MIPS_DSPR2;
michael@0 320 }
michael@0 321 }
michael@0 322 }
michael@0 323 #endif
michael@0 324
michael@0 325 if (dst_y) {
michael@0 326 if (src_stride_y0 == src_stride_y1) {
michael@0 327 CopyPlane(src_y, src_stride_y0, dst_y, dst_stride_y, width, height);
michael@0 328 } else {
michael@0 329 CopyPlane2(src_y, src_stride_y0, src_stride_y1, dst_y, dst_stride_y,
michael@0 330 width, height);
michael@0 331 }
michael@0 332 }
michael@0 333
michael@0 334 for (int y = 0; y < halfheight; ++y) {
michael@0 335 // Copy a row of UV.
michael@0 336 SplitUVRow(src_uv, dst_u, dst_v, halfwidth);
michael@0 337 dst_u += dst_stride_u;
michael@0 338 dst_v += dst_stride_v;
michael@0 339 src_uv += src_stride_uv;
michael@0 340 }
michael@0 341 return 0;
michael@0 342 }
michael@0 343
michael@0 344 // Convert NV12 to I420.
michael@0 345 LIBYUV_API
michael@0 346 int NV12ToI420(const uint8* src_y, int src_stride_y,
michael@0 347 const uint8* src_uv, int src_stride_uv,
michael@0 348 uint8* dst_y, int dst_stride_y,
michael@0 349 uint8* dst_u, int dst_stride_u,
michael@0 350 uint8* dst_v, int dst_stride_v,
michael@0 351 int width, int height) {
michael@0 352 return X420ToI420(src_y, src_stride_y, src_stride_y,
michael@0 353 src_uv, src_stride_uv,
michael@0 354 dst_y, dst_stride_y,
michael@0 355 dst_u, dst_stride_u,
michael@0 356 dst_v, dst_stride_v,
michael@0 357 width, height);
michael@0 358 }
michael@0 359
michael@0 360 // Convert NV21 to I420. Same as NV12 but u and v pointers swapped.
michael@0 361 LIBYUV_API
michael@0 362 int NV21ToI420(const uint8* src_y, int src_stride_y,
michael@0 363 const uint8* src_vu, int src_stride_vu,
michael@0 364 uint8* dst_y, int dst_stride_y,
michael@0 365 uint8* dst_u, int dst_stride_u,
michael@0 366 uint8* dst_v, int dst_stride_v,
michael@0 367 int width, int height) {
michael@0 368 return X420ToI420(src_y, src_stride_y, src_stride_y,
michael@0 369 src_vu, src_stride_vu,
michael@0 370 dst_y, dst_stride_y,
michael@0 371 dst_v, dst_stride_v,
michael@0 372 dst_u, dst_stride_u,
michael@0 373 width, height);
michael@0 374 }
michael@0 375
michael@0 376 // Convert M420 to I420.
michael@0 377 LIBYUV_API
michael@0 378 int M420ToI420(const uint8* src_m420, int src_stride_m420,
michael@0 379 uint8* dst_y, int dst_stride_y,
michael@0 380 uint8* dst_u, int dst_stride_u,
michael@0 381 uint8* dst_v, int dst_stride_v,
michael@0 382 int width, int height) {
michael@0 383 return X420ToI420(src_m420, src_stride_m420, src_stride_m420 * 2,
michael@0 384 src_m420 + src_stride_m420 * 2, src_stride_m420 * 3,
michael@0 385 dst_y, dst_stride_y,
michael@0 386 dst_u, dst_stride_u,
michael@0 387 dst_v, dst_stride_v,
michael@0 388 width, height);
michael@0 389 }
michael@0 390
michael@0 391 // Convert Q420 to I420.
michael@0 392 // Format is rows of YY/YUYV
michael@0 393 LIBYUV_API
michael@0 394 int Q420ToI420(const uint8* src_y, int src_stride_y,
michael@0 395 const uint8* src_yuy2, int src_stride_yuy2,
michael@0 396 uint8* dst_y, int dst_stride_y,
michael@0 397 uint8* dst_u, int dst_stride_u,
michael@0 398 uint8* dst_v, int dst_stride_v,
michael@0 399 int width, int height) {
michael@0 400 if (!src_y || !src_yuy2 ||
michael@0 401 !dst_y || !dst_u || !dst_v ||
michael@0 402 width <= 0 || height == 0) {
michael@0 403 return -1;
michael@0 404 }
michael@0 405 // Negative height means invert the image.
michael@0 406 if (height < 0) {
michael@0 407 height = -height;
michael@0 408 int halfheight = (height + 1) >> 1;
michael@0 409 dst_y = dst_y + (height - 1) * dst_stride_y;
michael@0 410 dst_u = dst_u + (halfheight - 1) * dst_stride_u;
michael@0 411 dst_v = dst_v + (halfheight - 1) * dst_stride_v;
michael@0 412 dst_stride_y = -dst_stride_y;
michael@0 413 dst_stride_u = -dst_stride_u;
michael@0 414 dst_stride_v = -dst_stride_v;
michael@0 415 }
michael@0 416 // CopyRow for rows of just Y in Q420 copied to Y plane of I420.
michael@0 417 void (*CopyRow)(const uint8* src, uint8* dst, int width) = CopyRow_C;
michael@0 418 #if defined(HAS_COPYROW_NEON)
michael@0 419 if (TestCpuFlag(kCpuHasNEON) && IS_ALIGNED(width, 32)) {
michael@0 420 CopyRow = CopyRow_NEON;
michael@0 421 }
michael@0 422 #endif
michael@0 423 #if defined(HAS_COPYROW_X86)
michael@0 424 if (IS_ALIGNED(width, 4)) {
michael@0 425 CopyRow = CopyRow_X86;
michael@0 426 }
michael@0 427 #endif
michael@0 428 #if defined(HAS_COPYROW_SSE2)
michael@0 429 if (TestCpuFlag(kCpuHasSSE2) && IS_ALIGNED(width, 32) &&
michael@0 430 IS_ALIGNED(src_y, 16) && IS_ALIGNED(src_stride_y, 16) &&
michael@0 431 IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
michael@0 432 CopyRow = CopyRow_SSE2;
michael@0 433 }
michael@0 434 #endif
michael@0 435 #if defined(HAS_COPYROW_ERMS)
michael@0 436 if (TestCpuFlag(kCpuHasERMS)) {
michael@0 437 CopyRow = CopyRow_ERMS;
michael@0 438 }
michael@0 439 #endif
michael@0 440 #if defined(HAS_COPYROW_MIPS)
michael@0 441 if (TestCpuFlag(kCpuHasMIPS)) {
michael@0 442 CopyRow = CopyRow_MIPS;
michael@0 443 }
michael@0 444 #endif
michael@0 445
michael@0 446 void (*YUY2ToUV422Row)(const uint8* src_yuy2, uint8* dst_u, uint8* dst_v,
michael@0 447 int pix) = YUY2ToUV422Row_C;
michael@0 448 void (*YUY2ToYRow)(const uint8* src_yuy2, uint8* dst_y, int pix) =
michael@0 449 YUY2ToYRow_C;
michael@0 450 #if defined(HAS_YUY2TOYROW_SSE2)
michael@0 451 if (TestCpuFlag(kCpuHasSSE2) && width >= 16) {
michael@0 452 YUY2ToUV422Row = YUY2ToUV422Row_Any_SSE2;
michael@0 453 YUY2ToYRow = YUY2ToYRow_Any_SSE2;
michael@0 454 if (IS_ALIGNED(width, 16)) {
michael@0 455 YUY2ToUV422Row = YUY2ToUV422Row_Unaligned_SSE2;
michael@0 456 YUY2ToYRow = YUY2ToYRow_Unaligned_SSE2;
michael@0 457 if (IS_ALIGNED(src_yuy2, 16) && IS_ALIGNED(src_stride_yuy2, 16)) {
michael@0 458 YUY2ToUV422Row = YUY2ToUV422Row_SSE2;
michael@0 459 if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
michael@0 460 YUY2ToYRow = YUY2ToYRow_SSE2;
michael@0 461 }
michael@0 462 }
michael@0 463 }
michael@0 464 }
michael@0 465 #endif
michael@0 466 #if defined(HAS_YUY2TOYROW_AVX2)
michael@0 467 if (TestCpuFlag(kCpuHasAVX2) && width >= 32) {
michael@0 468 YUY2ToUV422Row = YUY2ToUV422Row_Any_AVX2;
michael@0 469 YUY2ToYRow = YUY2ToYRow_Any_AVX2;
michael@0 470 if (IS_ALIGNED(width, 32)) {
michael@0 471 YUY2ToUV422Row = YUY2ToUV422Row_AVX2;
michael@0 472 YUY2ToYRow = YUY2ToYRow_AVX2;
michael@0 473 }
michael@0 474 }
michael@0 475 #endif
michael@0 476 #if defined(HAS_YUY2TOYROW_NEON)
michael@0 477 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
michael@0 478 YUY2ToYRow = YUY2ToYRow_Any_NEON;
michael@0 479 if (width >= 16) {
michael@0 480 YUY2ToUV422Row = YUY2ToUV422Row_Any_NEON;
michael@0 481 }
michael@0 482 if (IS_ALIGNED(width, 16)) {
michael@0 483 YUY2ToYRow = YUY2ToYRow_NEON;
michael@0 484 YUY2ToUV422Row = YUY2ToUV422Row_NEON;
michael@0 485 }
michael@0 486 }
michael@0 487 #endif
michael@0 488
michael@0 489 for (int y = 0; y < height - 1; y += 2) {
michael@0 490 CopyRow(src_y, dst_y, width);
michael@0 491 src_y += src_stride_y;
michael@0 492 dst_y += dst_stride_y;
michael@0 493
michael@0 494 YUY2ToUV422Row(src_yuy2, dst_u, dst_v, width);
michael@0 495 YUY2ToYRow(src_yuy2, dst_y, width);
michael@0 496 src_yuy2 += src_stride_yuy2;
michael@0 497 dst_y += dst_stride_y;
michael@0 498 dst_u += dst_stride_u;
michael@0 499 dst_v += dst_stride_v;
michael@0 500 }
michael@0 501 if (height & 1) {
michael@0 502 CopyRow(src_y, dst_y, width);
michael@0 503 YUY2ToUV422Row(src_yuy2, dst_u, dst_v, width);
michael@0 504 }
michael@0 505 return 0;
michael@0 506 }
michael@0 507
michael@0 508 // Convert YUY2 to I420.
michael@0 509 LIBYUV_API
michael@0 510 int YUY2ToI420(const uint8* src_yuy2, int src_stride_yuy2,
michael@0 511 uint8* dst_y, int dst_stride_y,
michael@0 512 uint8* dst_u, int dst_stride_u,
michael@0 513 uint8* dst_v, int dst_stride_v,
michael@0 514 int width, int height) {
michael@0 515 // Negative height means invert the image.
michael@0 516 if (height < 0) {
michael@0 517 height = -height;
michael@0 518 src_yuy2 = src_yuy2 + (height - 1) * src_stride_yuy2;
michael@0 519 src_stride_yuy2 = -src_stride_yuy2;
michael@0 520 }
michael@0 521 void (*YUY2ToUVRow)(const uint8* src_yuy2, int src_stride_yuy2,
michael@0 522 uint8* dst_u, uint8* dst_v, int pix);
michael@0 523 void (*YUY2ToYRow)(const uint8* src_yuy2,
michael@0 524 uint8* dst_y, int pix);
michael@0 525 YUY2ToYRow = YUY2ToYRow_C;
michael@0 526 YUY2ToUVRow = YUY2ToUVRow_C;
michael@0 527 #if defined(HAS_YUY2TOYROW_SSE2)
michael@0 528 if (TestCpuFlag(kCpuHasSSE2) && width >= 16) {
michael@0 529 YUY2ToUVRow = YUY2ToUVRow_Any_SSE2;
michael@0 530 YUY2ToYRow = YUY2ToYRow_Any_SSE2;
michael@0 531 if (IS_ALIGNED(width, 16)) {
michael@0 532 YUY2ToUVRow = YUY2ToUVRow_Unaligned_SSE2;
michael@0 533 YUY2ToYRow = YUY2ToYRow_Unaligned_SSE2;
michael@0 534 if (IS_ALIGNED(src_yuy2, 16) && IS_ALIGNED(src_stride_yuy2, 16)) {
michael@0 535 YUY2ToUVRow = YUY2ToUVRow_SSE2;
michael@0 536 if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
michael@0 537 YUY2ToYRow = YUY2ToYRow_SSE2;
michael@0 538 }
michael@0 539 }
michael@0 540 }
michael@0 541 }
michael@0 542 #endif
michael@0 543 #if defined(HAS_YUY2TOYROW_AVX2)
michael@0 544 if (TestCpuFlag(kCpuHasAVX2) && width >= 32) {
michael@0 545 YUY2ToUVRow = YUY2ToUVRow_Any_AVX2;
michael@0 546 YUY2ToYRow = YUY2ToYRow_Any_AVX2;
michael@0 547 if (IS_ALIGNED(width, 32)) {
michael@0 548 YUY2ToUVRow = YUY2ToUVRow_AVX2;
michael@0 549 YUY2ToYRow = YUY2ToYRow_AVX2;
michael@0 550 }
michael@0 551 }
michael@0 552 #endif
michael@0 553 #if defined(HAS_YUY2TOYROW_NEON)
michael@0 554 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
michael@0 555 YUY2ToYRow = YUY2ToYRow_Any_NEON;
michael@0 556 if (width >= 16) {
michael@0 557 YUY2ToUVRow = YUY2ToUVRow_Any_NEON;
michael@0 558 }
michael@0 559 if (IS_ALIGNED(width, 16)) {
michael@0 560 YUY2ToYRow = YUY2ToYRow_NEON;
michael@0 561 YUY2ToUVRow = YUY2ToUVRow_NEON;
michael@0 562 }
michael@0 563 }
michael@0 564 #endif
michael@0 565
michael@0 566 for (int y = 0; y < height - 1; y += 2) {
michael@0 567 YUY2ToUVRow(src_yuy2, src_stride_yuy2, dst_u, dst_v, width);
michael@0 568 YUY2ToYRow(src_yuy2, dst_y, width);
michael@0 569 YUY2ToYRow(src_yuy2 + src_stride_yuy2, dst_y + dst_stride_y, width);
michael@0 570 src_yuy2 += src_stride_yuy2 * 2;
michael@0 571 dst_y += dst_stride_y * 2;
michael@0 572 dst_u += dst_stride_u;
michael@0 573 dst_v += dst_stride_v;
michael@0 574 }
michael@0 575 if (height & 1) {
michael@0 576 YUY2ToUVRow(src_yuy2, 0, dst_u, dst_v, width);
michael@0 577 YUY2ToYRow(src_yuy2, dst_y, width);
michael@0 578 }
michael@0 579 return 0;
michael@0 580 }
michael@0 581
michael@0 582 // Convert UYVY to I420.
michael@0 583 LIBYUV_API
michael@0 584 int UYVYToI420(const uint8* src_uyvy, int src_stride_uyvy,
michael@0 585 uint8* dst_y, int dst_stride_y,
michael@0 586 uint8* dst_u, int dst_stride_u,
michael@0 587 uint8* dst_v, int dst_stride_v,
michael@0 588 int width, int height) {
michael@0 589 // Negative height means invert the image.
michael@0 590 if (height < 0) {
michael@0 591 height = -height;
michael@0 592 src_uyvy = src_uyvy + (height - 1) * src_stride_uyvy;
michael@0 593 src_stride_uyvy = -src_stride_uyvy;
michael@0 594 }
michael@0 595 void (*UYVYToUVRow)(const uint8* src_uyvy, int src_stride_uyvy,
michael@0 596 uint8* dst_u, uint8* dst_v, int pix);
michael@0 597 void (*UYVYToYRow)(const uint8* src_uyvy,
michael@0 598 uint8* dst_y, int pix);
michael@0 599 UYVYToYRow = UYVYToYRow_C;
michael@0 600 UYVYToUVRow = UYVYToUVRow_C;
michael@0 601 #if defined(HAS_UYVYTOYROW_SSE2)
michael@0 602 if (TestCpuFlag(kCpuHasSSE2) && width >= 16) {
michael@0 603 UYVYToUVRow = UYVYToUVRow_Any_SSE2;
michael@0 604 UYVYToYRow = UYVYToYRow_Any_SSE2;
michael@0 605 if (IS_ALIGNED(width, 16)) {
michael@0 606 UYVYToUVRow = UYVYToUVRow_Unaligned_SSE2;
michael@0 607 UYVYToYRow = UYVYToYRow_Unaligned_SSE2;
michael@0 608 if (IS_ALIGNED(src_uyvy, 16) && IS_ALIGNED(src_stride_uyvy, 16)) {
michael@0 609 UYVYToUVRow = UYVYToUVRow_SSE2;
michael@0 610 if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
michael@0 611 UYVYToYRow = UYVYToYRow_SSE2;
michael@0 612 }
michael@0 613 }
michael@0 614 }
michael@0 615 }
michael@0 616 #endif
michael@0 617 #if defined(HAS_UYVYTOYROW_AVX2)
michael@0 618 if (TestCpuFlag(kCpuHasAVX2) && width >= 32) {
michael@0 619 UYVYToUVRow = UYVYToUVRow_Any_AVX2;
michael@0 620 UYVYToYRow = UYVYToYRow_Any_AVX2;
michael@0 621 if (IS_ALIGNED(width, 32)) {
michael@0 622 UYVYToUVRow = UYVYToUVRow_AVX2;
michael@0 623 UYVYToYRow = UYVYToYRow_AVX2;
michael@0 624 }
michael@0 625 }
michael@0 626 #endif
michael@0 627 #if defined(HAS_UYVYTOYROW_NEON)
michael@0 628 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
michael@0 629 UYVYToYRow = UYVYToYRow_Any_NEON;
michael@0 630 if (width >= 16) {
michael@0 631 UYVYToUVRow = UYVYToUVRow_Any_NEON;
michael@0 632 }
michael@0 633 if (IS_ALIGNED(width, 16)) {
michael@0 634 UYVYToYRow = UYVYToYRow_NEON;
michael@0 635 UYVYToUVRow = UYVYToUVRow_NEON;
michael@0 636 }
michael@0 637 }
michael@0 638 #endif
michael@0 639
michael@0 640 for (int y = 0; y < height - 1; y += 2) {
michael@0 641 UYVYToUVRow(src_uyvy, src_stride_uyvy, dst_u, dst_v, width);
michael@0 642 UYVYToYRow(src_uyvy, dst_y, width);
michael@0 643 UYVYToYRow(src_uyvy + src_stride_uyvy, dst_y + dst_stride_y, width);
michael@0 644 src_uyvy += src_stride_uyvy * 2;
michael@0 645 dst_y += dst_stride_y * 2;
michael@0 646 dst_u += dst_stride_u;
michael@0 647 dst_v += dst_stride_v;
michael@0 648 }
michael@0 649 if (height & 1) {
michael@0 650 UYVYToUVRow(src_uyvy, 0, dst_u, dst_v, width);
michael@0 651 UYVYToYRow(src_uyvy, dst_y, width);
michael@0 652 }
michael@0 653 return 0;
michael@0 654 }
michael@0 655
michael@0 656 // Convert ARGB to I420.
michael@0 657 LIBYUV_API
michael@0 658 int ARGBToI420(const uint8* src_argb, int src_stride_argb,
michael@0 659 uint8* dst_y, int dst_stride_y,
michael@0 660 uint8* dst_u, int dst_stride_u,
michael@0 661 uint8* dst_v, int dst_stride_v,
michael@0 662 int width, int height) {
michael@0 663 if (!src_argb ||
michael@0 664 !dst_y || !dst_u || !dst_v ||
michael@0 665 width <= 0 || height == 0) {
michael@0 666 return -1;
michael@0 667 }
michael@0 668 // Negative height means invert the image.
michael@0 669 if (height < 0) {
michael@0 670 height = -height;
michael@0 671 src_argb = src_argb + (height - 1) * src_stride_argb;
michael@0 672 src_stride_argb = -src_stride_argb;
michael@0 673 }
michael@0 674 void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb,
michael@0 675 uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C;
michael@0 676 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
michael@0 677 ARGBToYRow_C;
michael@0 678 #if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3)
michael@0 679 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
michael@0 680 ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
michael@0 681 ARGBToYRow = ARGBToYRow_Any_SSSE3;
michael@0 682 if (IS_ALIGNED(width, 16)) {
michael@0 683 ARGBToUVRow = ARGBToUVRow_Unaligned_SSSE3;
michael@0 684 ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
michael@0 685 if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
michael@0 686 ARGBToUVRow = ARGBToUVRow_SSSE3;
michael@0 687 if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
michael@0 688 ARGBToYRow = ARGBToYRow_SSSE3;
michael@0 689 }
michael@0 690 }
michael@0 691 }
michael@0 692 }
michael@0 693 #endif
michael@0 694 #if defined(HAS_ARGBTOYROW_AVX2) && defined(HAS_ARGBTOUVROW_AVX2)
michael@0 695 if (TestCpuFlag(kCpuHasAVX2) && width >= 32) {
michael@0 696 ARGBToUVRow = ARGBToUVRow_Any_AVX2;
michael@0 697 ARGBToYRow = ARGBToYRow_Any_AVX2;
michael@0 698 if (IS_ALIGNED(width, 32)) {
michael@0 699 ARGBToUVRow = ARGBToUVRow_AVX2;
michael@0 700 ARGBToYRow = ARGBToYRow_AVX2;
michael@0 701 }
michael@0 702 }
michael@0 703 #endif
michael@0 704 #if defined(HAS_ARGBTOYROW_NEON)
michael@0 705 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
michael@0 706 ARGBToYRow = ARGBToYRow_Any_NEON;
michael@0 707 if (IS_ALIGNED(width, 8)) {
michael@0 708 ARGBToYRow = ARGBToYRow_NEON;
michael@0 709 }
michael@0 710 if (width >= 16) {
michael@0 711 ARGBToUVRow = ARGBToUVRow_Any_NEON;
michael@0 712 if (IS_ALIGNED(width, 16)) {
michael@0 713 ARGBToUVRow = ARGBToUVRow_NEON;
michael@0 714 }
michael@0 715 }
michael@0 716 }
michael@0 717 #endif
michael@0 718
michael@0 719 for (int y = 0; y < height - 1; y += 2) {
michael@0 720 ARGBToUVRow(src_argb, src_stride_argb, dst_u, dst_v, width);
michael@0 721 ARGBToYRow(src_argb, dst_y, width);
michael@0 722 ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width);
michael@0 723 src_argb += src_stride_argb * 2;
michael@0 724 dst_y += dst_stride_y * 2;
michael@0 725 dst_u += dst_stride_u;
michael@0 726 dst_v += dst_stride_v;
michael@0 727 }
michael@0 728 if (height & 1) {
michael@0 729 ARGBToUVRow(src_argb, 0, dst_u, dst_v, width);
michael@0 730 ARGBToYRow(src_argb, dst_y, width);
michael@0 731 }
michael@0 732 return 0;
michael@0 733 }
michael@0 734
michael@0 735 // Convert BGRA to I420.
michael@0 736 LIBYUV_API
michael@0 737 int BGRAToI420(const uint8* src_bgra, int src_stride_bgra,
michael@0 738 uint8* dst_y, int dst_stride_y,
michael@0 739 uint8* dst_u, int dst_stride_u,
michael@0 740 uint8* dst_v, int dst_stride_v,
michael@0 741 int width, int height) {
michael@0 742 if (!src_bgra ||
michael@0 743 !dst_y || !dst_u || !dst_v ||
michael@0 744 width <= 0 || height == 0) {
michael@0 745 return -1;
michael@0 746 }
michael@0 747 // Negative height means invert the image.
michael@0 748 if (height < 0) {
michael@0 749 height = -height;
michael@0 750 src_bgra = src_bgra + (height - 1) * src_stride_bgra;
michael@0 751 src_stride_bgra = -src_stride_bgra;
michael@0 752 }
michael@0 753 void (*BGRAToUVRow)(const uint8* src_bgra0, int src_stride_bgra,
michael@0 754 uint8* dst_u, uint8* dst_v, int width) = BGRAToUVRow_C;
michael@0 755 void (*BGRAToYRow)(const uint8* src_bgra, uint8* dst_y, int pix) =
michael@0 756 BGRAToYRow_C;
michael@0 757 #if defined(HAS_BGRATOYROW_SSSE3)
michael@0 758 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
michael@0 759 BGRAToUVRow = BGRAToUVRow_Any_SSSE3;
michael@0 760 BGRAToYRow = BGRAToYRow_Any_SSSE3;
michael@0 761 if (IS_ALIGNED(width, 16)) {
michael@0 762 BGRAToUVRow = BGRAToUVRow_Unaligned_SSSE3;
michael@0 763 BGRAToYRow = BGRAToYRow_Unaligned_SSSE3;
michael@0 764 if (IS_ALIGNED(src_bgra, 16) && IS_ALIGNED(src_stride_bgra, 16)) {
michael@0 765 BGRAToUVRow = BGRAToUVRow_SSSE3;
michael@0 766 if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
michael@0 767 BGRAToYRow = BGRAToYRow_SSSE3;
michael@0 768 }
michael@0 769 }
michael@0 770 }
michael@0 771 }
michael@0 772 #elif defined(HAS_BGRATOYROW_NEON)
michael@0 773 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
michael@0 774 BGRAToYRow = BGRAToYRow_Any_NEON;
michael@0 775 if (IS_ALIGNED(width, 8)) {
michael@0 776 BGRAToYRow = BGRAToYRow_NEON;
michael@0 777 }
michael@0 778 if (width >= 16) {
michael@0 779 BGRAToUVRow = BGRAToUVRow_Any_NEON;
michael@0 780 if (IS_ALIGNED(width, 16)) {
michael@0 781 BGRAToUVRow = BGRAToUVRow_NEON;
michael@0 782 }
michael@0 783 }
michael@0 784 }
michael@0 785 #endif
michael@0 786
michael@0 787 for (int y = 0; y < height - 1; y += 2) {
michael@0 788 BGRAToUVRow(src_bgra, src_stride_bgra, dst_u, dst_v, width);
michael@0 789 BGRAToYRow(src_bgra, dst_y, width);
michael@0 790 BGRAToYRow(src_bgra + src_stride_bgra, dst_y + dst_stride_y, width);
michael@0 791 src_bgra += src_stride_bgra * 2;
michael@0 792 dst_y += dst_stride_y * 2;
michael@0 793 dst_u += dst_stride_u;
michael@0 794 dst_v += dst_stride_v;
michael@0 795 }
michael@0 796 if (height & 1) {
michael@0 797 BGRAToUVRow(src_bgra, 0, dst_u, dst_v, width);
michael@0 798 BGRAToYRow(src_bgra, dst_y, width);
michael@0 799 }
michael@0 800 return 0;
michael@0 801 }
michael@0 802
michael@0 803 // Convert ABGR to I420.
michael@0 804 LIBYUV_API
michael@0 805 int ABGRToI420(const uint8* src_abgr, int src_stride_abgr,
michael@0 806 uint8* dst_y, int dst_stride_y,
michael@0 807 uint8* dst_u, int dst_stride_u,
michael@0 808 uint8* dst_v, int dst_stride_v,
michael@0 809 int width, int height) {
michael@0 810 if (!src_abgr ||
michael@0 811 !dst_y || !dst_u || !dst_v ||
michael@0 812 width <= 0 || height == 0) {
michael@0 813 return -1;
michael@0 814 }
michael@0 815 // Negative height means invert the image.
michael@0 816 if (height < 0) {
michael@0 817 height = -height;
michael@0 818 src_abgr = src_abgr + (height - 1) * src_stride_abgr;
michael@0 819 src_stride_abgr = -src_stride_abgr;
michael@0 820 }
michael@0 821 void (*ABGRToUVRow)(const uint8* src_abgr0, int src_stride_abgr,
michael@0 822 uint8* dst_u, uint8* dst_v, int width) = ABGRToUVRow_C;
michael@0 823 void (*ABGRToYRow)(const uint8* src_abgr, uint8* dst_y, int pix) =
michael@0 824 ABGRToYRow_C;
michael@0 825 #if defined(HAS_ABGRTOYROW_SSSE3)
michael@0 826 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
michael@0 827 ABGRToUVRow = ABGRToUVRow_Any_SSSE3;
michael@0 828 ABGRToYRow = ABGRToYRow_Any_SSSE3;
michael@0 829 if (IS_ALIGNED(width, 16)) {
michael@0 830 ABGRToUVRow = ABGRToUVRow_Unaligned_SSSE3;
michael@0 831 ABGRToYRow = ABGRToYRow_Unaligned_SSSE3;
michael@0 832 if (IS_ALIGNED(src_abgr, 16) && IS_ALIGNED(src_stride_abgr, 16)) {
michael@0 833 ABGRToUVRow = ABGRToUVRow_SSSE3;
michael@0 834 if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
michael@0 835 ABGRToYRow = ABGRToYRow_SSSE3;
michael@0 836 }
michael@0 837 }
michael@0 838 }
michael@0 839 }
michael@0 840 #elif defined(HAS_ABGRTOYROW_NEON)
michael@0 841 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
michael@0 842 ABGRToYRow = ABGRToYRow_Any_NEON;
michael@0 843 if (IS_ALIGNED(width, 8)) {
michael@0 844 ABGRToYRow = ABGRToYRow_NEON;
michael@0 845 }
michael@0 846 if (width >= 16) {
michael@0 847 ABGRToUVRow = ABGRToUVRow_Any_NEON;
michael@0 848 if (IS_ALIGNED(width, 16)) {
michael@0 849 ABGRToUVRow = ABGRToUVRow_NEON;
michael@0 850 }
michael@0 851 }
michael@0 852 }
michael@0 853 #endif
michael@0 854
michael@0 855 for (int y = 0; y < height - 1; y += 2) {
michael@0 856 ABGRToUVRow(src_abgr, src_stride_abgr, dst_u, dst_v, width);
michael@0 857 ABGRToYRow(src_abgr, dst_y, width);
michael@0 858 ABGRToYRow(src_abgr + src_stride_abgr, dst_y + dst_stride_y, width);
michael@0 859 src_abgr += src_stride_abgr * 2;
michael@0 860 dst_y += dst_stride_y * 2;
michael@0 861 dst_u += dst_stride_u;
michael@0 862 dst_v += dst_stride_v;
michael@0 863 }
michael@0 864 if (height & 1) {
michael@0 865 ABGRToUVRow(src_abgr, 0, dst_u, dst_v, width);
michael@0 866 ABGRToYRow(src_abgr, dst_y, width);
michael@0 867 }
michael@0 868 return 0;
michael@0 869 }
michael@0 870
michael@0 871 // Convert RGBA to I420.
michael@0 872 LIBYUV_API
michael@0 873 int RGBAToI420(const uint8* src_rgba, int src_stride_rgba,
michael@0 874 uint8* dst_y, int dst_stride_y,
michael@0 875 uint8* dst_u, int dst_stride_u,
michael@0 876 uint8* dst_v, int dst_stride_v,
michael@0 877 int width, int height) {
michael@0 878 if (!src_rgba ||
michael@0 879 !dst_y || !dst_u || !dst_v ||
michael@0 880 width <= 0 || height == 0) {
michael@0 881 return -1;
michael@0 882 }
michael@0 883 // Negative height means invert the image.
michael@0 884 if (height < 0) {
michael@0 885 height = -height;
michael@0 886 src_rgba = src_rgba + (height - 1) * src_stride_rgba;
michael@0 887 src_stride_rgba = -src_stride_rgba;
michael@0 888 }
michael@0 889 void (*RGBAToUVRow)(const uint8* src_rgba0, int src_stride_rgba,
michael@0 890 uint8* dst_u, uint8* dst_v, int width) = RGBAToUVRow_C;
michael@0 891 void (*RGBAToYRow)(const uint8* src_rgba, uint8* dst_y, int pix) =
michael@0 892 RGBAToYRow_C;
michael@0 893 #if defined(HAS_RGBATOYROW_SSSE3)
michael@0 894 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
michael@0 895 RGBAToUVRow = RGBAToUVRow_Any_SSSE3;
michael@0 896 RGBAToYRow = RGBAToYRow_Any_SSSE3;
michael@0 897 if (IS_ALIGNED(width, 16)) {
michael@0 898 RGBAToUVRow = RGBAToUVRow_Unaligned_SSSE3;
michael@0 899 RGBAToYRow = RGBAToYRow_Unaligned_SSSE3;
michael@0 900 if (IS_ALIGNED(src_rgba, 16) && IS_ALIGNED(src_stride_rgba, 16)) {
michael@0 901 RGBAToUVRow = RGBAToUVRow_SSSE3;
michael@0 902 if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
michael@0 903 RGBAToYRow = RGBAToYRow_SSSE3;
michael@0 904 }
michael@0 905 }
michael@0 906 }
michael@0 907 }
michael@0 908 #elif defined(HAS_RGBATOYROW_NEON)
michael@0 909 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
michael@0 910 RGBAToYRow = RGBAToYRow_Any_NEON;
michael@0 911 if (IS_ALIGNED(width, 8)) {
michael@0 912 RGBAToYRow = RGBAToYRow_NEON;
michael@0 913 }
michael@0 914 if (width >= 16) {
michael@0 915 RGBAToUVRow = RGBAToUVRow_Any_NEON;
michael@0 916 if (IS_ALIGNED(width, 16)) {
michael@0 917 RGBAToUVRow = RGBAToUVRow_NEON;
michael@0 918 }
michael@0 919 }
michael@0 920 }
michael@0 921 #endif
michael@0 922
michael@0 923 for (int y = 0; y < height - 1; y += 2) {
michael@0 924 RGBAToUVRow(src_rgba, src_stride_rgba, dst_u, dst_v, width);
michael@0 925 RGBAToYRow(src_rgba, dst_y, width);
michael@0 926 RGBAToYRow(src_rgba + src_stride_rgba, dst_y + dst_stride_y, width);
michael@0 927 src_rgba += src_stride_rgba * 2;
michael@0 928 dst_y += dst_stride_y * 2;
michael@0 929 dst_u += dst_stride_u;
michael@0 930 dst_v += dst_stride_v;
michael@0 931 }
michael@0 932 if (height & 1) {
michael@0 933 RGBAToUVRow(src_rgba, 0, dst_u, dst_v, width);
michael@0 934 RGBAToYRow(src_rgba, dst_y, width);
michael@0 935 }
michael@0 936 return 0;
michael@0 937 }
michael@0 938
michael@0 939 // Convert RGB24 to I420.
michael@0 940 LIBYUV_API
michael@0 941 int RGB24ToI420(const uint8* src_rgb24, int src_stride_rgb24,
michael@0 942 uint8* dst_y, int dst_stride_y,
michael@0 943 uint8* dst_u, int dst_stride_u,
michael@0 944 uint8* dst_v, int dst_stride_v,
michael@0 945 int width, int height) {
michael@0 946 if (!src_rgb24 || !dst_y || !dst_u || !dst_v ||
michael@0 947 width <= 0 || height == 0) {
michael@0 948 return -1;
michael@0 949 }
michael@0 950 // Negative height means invert the image.
michael@0 951 if (height < 0) {
michael@0 952 height = -height;
michael@0 953 src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24;
michael@0 954 src_stride_rgb24 = -src_stride_rgb24;
michael@0 955 }
michael@0 956
michael@0 957 #if defined(HAS_RGB24TOYROW_NEON)
michael@0 958 void (*RGB24ToUVRow)(const uint8* src_rgb24, int src_stride_rgb24,
michael@0 959 uint8* dst_u, uint8* dst_v, int width) = RGB24ToUVRow_C;
michael@0 960 void (*RGB24ToYRow)(const uint8* src_rgb24, uint8* dst_y, int pix) =
michael@0 961 RGB24ToYRow_C;
michael@0 962 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
michael@0 963 RGB24ToYRow = RGB24ToYRow_Any_NEON;
michael@0 964 if (IS_ALIGNED(width, 8)) {
michael@0 965 RGB24ToYRow = RGB24ToYRow_NEON;
michael@0 966 }
michael@0 967 if (width >= 16) {
michael@0 968 RGB24ToUVRow = RGB24ToUVRow_Any_NEON;
michael@0 969 if (IS_ALIGNED(width, 16)) {
michael@0 970 RGB24ToUVRow = RGB24ToUVRow_NEON;
michael@0 971 }
michael@0 972 }
michael@0 973 }
michael@0 974 #else // HAS_RGB24TOYROW_NEON
michael@0 975
michael@0 976 // Allocate 2 rows of ARGB.
michael@0 977 const int kRowSize = (width * 4 + 15) & ~15;
michael@0 978 align_buffer_64(row, kRowSize * 2);
michael@0 979
michael@0 980 void (*RGB24ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) =
michael@0 981 RGB24ToARGBRow_C;
michael@0 982 #if defined(HAS_RGB24TOARGBROW_SSSE3)
michael@0 983 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
michael@0 984 RGB24ToARGBRow = RGB24ToARGBRow_Any_SSSE3;
michael@0 985 if (IS_ALIGNED(width, 16)) {
michael@0 986 RGB24ToARGBRow = RGB24ToARGBRow_SSSE3;
michael@0 987 }
michael@0 988 }
michael@0 989 #endif
michael@0 990 void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb,
michael@0 991 uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C;
michael@0 992 #if defined(HAS_ARGBTOUVROW_SSSE3)
michael@0 993 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
michael@0 994 ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
michael@0 995 if (IS_ALIGNED(width, 16)) {
michael@0 996 ARGBToUVRow = ARGBToUVRow_SSSE3;
michael@0 997 }
michael@0 998 }
michael@0 999 #endif
michael@0 1000 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
michael@0 1001 ARGBToYRow_C;
michael@0 1002 #if defined(HAS_ARGBTOUVROW_SSSE3)
michael@0 1003 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
michael@0 1004 ARGBToYRow = ARGBToYRow_Any_SSSE3;
michael@0 1005 if (IS_ALIGNED(width, 16)) {
michael@0 1006 ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
michael@0 1007 if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
michael@0 1008 ARGBToYRow = ARGBToYRow_SSSE3;
michael@0 1009 }
michael@0 1010 }
michael@0 1011 }
michael@0 1012 #endif // HAS_ARGBTOUVROW_SSSE3
michael@0 1013 #endif // HAS_RGB24TOYROW_NEON
michael@0 1014
michael@0 1015 for (int y = 0; y < height - 1; y += 2) {
michael@0 1016 #if defined(HAS_RGB24TOYROW_NEON)
michael@0 1017 RGB24ToUVRow(src_rgb24, src_stride_rgb24, dst_u, dst_v, width);
michael@0 1018 RGB24ToYRow(src_rgb24, dst_y, width);
michael@0 1019 RGB24ToYRow(src_rgb24 + src_stride_rgb24, dst_y + dst_stride_y, width);
michael@0 1020 #else
michael@0 1021 RGB24ToARGBRow(src_rgb24, row, width);
michael@0 1022 RGB24ToARGBRow(src_rgb24 + src_stride_rgb24, row + kRowSize, width);
michael@0 1023 ARGBToUVRow(row, kRowSize, dst_u, dst_v, width);
michael@0 1024 ARGBToYRow(row, dst_y, width);
michael@0 1025 ARGBToYRow(row + kRowSize, dst_y + dst_stride_y, width);
michael@0 1026 #endif
michael@0 1027 src_rgb24 += src_stride_rgb24 * 2;
michael@0 1028 dst_y += dst_stride_y * 2;
michael@0 1029 dst_u += dst_stride_u;
michael@0 1030 dst_v += dst_stride_v;
michael@0 1031 }
michael@0 1032 if (height & 1) {
michael@0 1033 #if defined(HAS_RGB24TOYROW_NEON)
michael@0 1034 RGB24ToUVRow(src_rgb24, 0, dst_u, dst_v, width);
michael@0 1035 RGB24ToYRow(src_rgb24, dst_y, width);
michael@0 1036 #else
michael@0 1037 RGB24ToARGBRow(src_rgb24, row, width);
michael@0 1038 ARGBToUVRow(row, 0, dst_u, dst_v, width);
michael@0 1039 ARGBToYRow(row, dst_y, width);
michael@0 1040 #endif
michael@0 1041 }
michael@0 1042 #if !defined(HAS_RGB24TOYROW_NEON)
michael@0 1043 free_aligned_buffer_64(row);
michael@0 1044 #endif
michael@0 1045 return 0;
michael@0 1046 }
michael@0 1047
michael@0 1048 // Convert RAW to I420.
michael@0 1049 LIBYUV_API
michael@0 1050 int RAWToI420(const uint8* src_raw, int src_stride_raw,
michael@0 1051 uint8* dst_y, int dst_stride_y,
michael@0 1052 uint8* dst_u, int dst_stride_u,
michael@0 1053 uint8* dst_v, int dst_stride_v,
michael@0 1054 int width, int height) {
michael@0 1055 if (!src_raw || !dst_y || !dst_u || !dst_v ||
michael@0 1056 width <= 0 || height == 0) {
michael@0 1057 return -1;
michael@0 1058 }
michael@0 1059 // Negative height means invert the image.
michael@0 1060 if (height < 0) {
michael@0 1061 height = -height;
michael@0 1062 src_raw = src_raw + (height - 1) * src_stride_raw;
michael@0 1063 src_stride_raw = -src_stride_raw;
michael@0 1064 }
michael@0 1065
michael@0 1066 #if defined(HAS_RAWTOYROW_NEON)
michael@0 1067 void (*RAWToUVRow)(const uint8* src_raw, int src_stride_raw,
michael@0 1068 uint8* dst_u, uint8* dst_v, int width) = RAWToUVRow_C;
michael@0 1069 void (*RAWToYRow)(const uint8* src_raw, uint8* dst_y, int pix) =
michael@0 1070 RAWToYRow_C;
michael@0 1071 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
michael@0 1072 RAWToYRow = RAWToYRow_Any_NEON;
michael@0 1073 if (IS_ALIGNED(width, 8)) {
michael@0 1074 RAWToYRow = RAWToYRow_NEON;
michael@0 1075 }
michael@0 1076 if (width >= 16) {
michael@0 1077 RAWToUVRow = RAWToUVRow_Any_NEON;
michael@0 1078 if (IS_ALIGNED(width, 16)) {
michael@0 1079 RAWToUVRow = RAWToUVRow_NEON;
michael@0 1080 }
michael@0 1081 }
michael@0 1082 }
michael@0 1083 #else // HAS_RAWTOYROW_NEON
michael@0 1084
michael@0 1085 // Allocate 2 rows of ARGB.
michael@0 1086 const int kRowSize = (width * 4 + 15) & ~15;
michael@0 1087 align_buffer_64(row, kRowSize * 2);
michael@0 1088
michael@0 1089 void (*RAWToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) =
michael@0 1090 RAWToARGBRow_C;
michael@0 1091 #if defined(HAS_RAWTOARGBROW_SSSE3)
michael@0 1092 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
michael@0 1093 RAWToARGBRow = RAWToARGBRow_Any_SSSE3;
michael@0 1094 if (IS_ALIGNED(width, 16)) {
michael@0 1095 RAWToARGBRow = RAWToARGBRow_SSSE3;
michael@0 1096 }
michael@0 1097 }
michael@0 1098 #endif
michael@0 1099 void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb,
michael@0 1100 uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C;
michael@0 1101 #if defined(HAS_ARGBTOUVROW_SSSE3)
michael@0 1102 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
michael@0 1103 ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
michael@0 1104 if (IS_ALIGNED(width, 16)) {
michael@0 1105 ARGBToUVRow = ARGBToUVRow_SSSE3;
michael@0 1106 }
michael@0 1107 }
michael@0 1108 #endif
michael@0 1109 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
michael@0 1110 ARGBToYRow_C;
michael@0 1111 #if defined(HAS_ARGBTOUVROW_SSSE3)
michael@0 1112 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
michael@0 1113 ARGBToYRow = ARGBToYRow_Any_SSSE3;
michael@0 1114 if (IS_ALIGNED(width, 16)) {
michael@0 1115 ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
michael@0 1116 if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
michael@0 1117 ARGBToYRow = ARGBToYRow_SSSE3;
michael@0 1118 }
michael@0 1119 }
michael@0 1120 }
michael@0 1121 #endif // HAS_ARGBTOUVROW_SSSE3
michael@0 1122 #endif // HAS_RAWTOYROW_NEON
michael@0 1123
michael@0 1124 for (int y = 0; y < height - 1; y += 2) {
michael@0 1125 #if defined(HAS_RAWTOYROW_NEON)
michael@0 1126 RAWToUVRow(src_raw, src_stride_raw, dst_u, dst_v, width);
michael@0 1127 RAWToYRow(src_raw, dst_y, width);
michael@0 1128 RAWToYRow(src_raw + src_stride_raw, dst_y + dst_stride_y, width);
michael@0 1129 #else
michael@0 1130 RAWToARGBRow(src_raw, row, width);
michael@0 1131 RAWToARGBRow(src_raw + src_stride_raw, row + kRowSize, width);
michael@0 1132 ARGBToUVRow(row, kRowSize, dst_u, dst_v, width);
michael@0 1133 ARGBToYRow(row, dst_y, width);
michael@0 1134 ARGBToYRow(row + kRowSize, dst_y + dst_stride_y, width);
michael@0 1135 #endif
michael@0 1136 src_raw += src_stride_raw * 2;
michael@0 1137 dst_y += dst_stride_y * 2;
michael@0 1138 dst_u += dst_stride_u;
michael@0 1139 dst_v += dst_stride_v;
michael@0 1140 }
michael@0 1141 if (height & 1) {
michael@0 1142 #if defined(HAS_RAWTOYROW_NEON)
michael@0 1143 RAWToUVRow(src_raw, 0, dst_u, dst_v, width);
michael@0 1144 RAWToYRow(src_raw, dst_y, width);
michael@0 1145 #else
michael@0 1146 RAWToARGBRow(src_raw, row, width);
michael@0 1147 ARGBToUVRow(row, 0, dst_u, dst_v, width);
michael@0 1148 ARGBToYRow(row, dst_y, width);
michael@0 1149 #endif
michael@0 1150 }
michael@0 1151 #if !defined(HAS_RAWTOYROW_NEON)
michael@0 1152 free_aligned_buffer_64(row);
michael@0 1153 #endif
michael@0 1154 return 0;
michael@0 1155 }
michael@0 1156
michael@0 1157 // Convert RGB565 to I420.
michael@0 1158 LIBYUV_API
michael@0 1159 int RGB565ToI420(const uint8* src_rgb565, int src_stride_rgb565,
michael@0 1160 uint8* dst_y, int dst_stride_y,
michael@0 1161 uint8* dst_u, int dst_stride_u,
michael@0 1162 uint8* dst_v, int dst_stride_v,
michael@0 1163 int width, int height) {
michael@0 1164 if (!src_rgb565 || !dst_y || !dst_u || !dst_v ||
michael@0 1165 width <= 0 || height == 0) {
michael@0 1166 return -1;
michael@0 1167 }
michael@0 1168 // Negative height means invert the image.
michael@0 1169 if (height < 0) {
michael@0 1170 height = -height;
michael@0 1171 src_rgb565 = src_rgb565 + (height - 1) * src_stride_rgb565;
michael@0 1172 src_stride_rgb565 = -src_stride_rgb565;
michael@0 1173 }
michael@0 1174
michael@0 1175 #if defined(HAS_RGB565TOYROW_NEON)
michael@0 1176 void (*RGB565ToUVRow)(const uint8* src_rgb565, int src_stride_rgb565,
michael@0 1177 uint8* dst_u, uint8* dst_v, int width) = RGB565ToUVRow_C;
michael@0 1178 void (*RGB565ToYRow)(const uint8* src_rgb565, uint8* dst_y, int pix) =
michael@0 1179 RGB565ToYRow_C;
michael@0 1180 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
michael@0 1181 RGB565ToYRow = RGB565ToYRow_Any_NEON;
michael@0 1182 if (IS_ALIGNED(width, 8)) {
michael@0 1183 RGB565ToYRow = RGB565ToYRow_NEON;
michael@0 1184 }
michael@0 1185 if (width >= 16) {
michael@0 1186 RGB565ToUVRow = RGB565ToUVRow_Any_NEON;
michael@0 1187 if (IS_ALIGNED(width, 16)) {
michael@0 1188 RGB565ToUVRow = RGB565ToUVRow_NEON;
michael@0 1189 }
michael@0 1190 }
michael@0 1191 }
michael@0 1192 #else // HAS_RGB565TOYROW_NEON
michael@0 1193
michael@0 1194 // Allocate 2 rows of ARGB.
michael@0 1195 const int kRowSize = (width * 4 + 15) & ~15;
michael@0 1196 align_buffer_64(row, kRowSize * 2);
michael@0 1197
michael@0 1198 void (*RGB565ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) =
michael@0 1199 RGB565ToARGBRow_C;
michael@0 1200 #if defined(HAS_RGB565TOARGBROW_SSE2)
michael@0 1201 if (TestCpuFlag(kCpuHasSSE2) && width >= 8) {
michael@0 1202 RGB565ToARGBRow = RGB565ToARGBRow_Any_SSE2;
michael@0 1203 if (IS_ALIGNED(width, 8)) {
michael@0 1204 RGB565ToARGBRow = RGB565ToARGBRow_SSE2;
michael@0 1205 }
michael@0 1206 }
michael@0 1207 #endif
michael@0 1208 void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb,
michael@0 1209 uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C;
michael@0 1210 #if defined(HAS_ARGBTOUVROW_SSSE3)
michael@0 1211 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
michael@0 1212 ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
michael@0 1213 if (IS_ALIGNED(width, 16)) {
michael@0 1214 ARGBToUVRow = ARGBToUVRow_SSSE3;
michael@0 1215 }
michael@0 1216 }
michael@0 1217 #endif
michael@0 1218 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
michael@0 1219 ARGBToYRow_C;
michael@0 1220 #if defined(HAS_ARGBTOUVROW_SSSE3)
michael@0 1221 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
michael@0 1222 ARGBToYRow = ARGBToYRow_Any_SSSE3;
michael@0 1223 if (IS_ALIGNED(width, 16)) {
michael@0 1224 ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
michael@0 1225 if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
michael@0 1226 ARGBToYRow = ARGBToYRow_SSSE3;
michael@0 1227 }
michael@0 1228 }
michael@0 1229 }
michael@0 1230 #endif // HAS_ARGBTOUVROW_SSSE3
michael@0 1231 #endif // HAS_RGB565TOYROW_NEON
michael@0 1232
michael@0 1233 for (int y = 0; y < height - 1; y += 2) {
michael@0 1234 #if defined(HAS_RGB565TOYROW_NEON)
michael@0 1235 RGB565ToUVRow(src_rgb565, src_stride_rgb565, dst_u, dst_v, width);
michael@0 1236 RGB565ToYRow(src_rgb565, dst_y, width);
michael@0 1237 RGB565ToYRow(src_rgb565 + src_stride_rgb565, dst_y + dst_stride_y, width);
michael@0 1238 #else
michael@0 1239 RGB565ToARGBRow(src_rgb565, row, width);
michael@0 1240 RGB565ToARGBRow(src_rgb565 + src_stride_rgb565, row + kRowSize, width);
michael@0 1241 ARGBToUVRow(row, kRowSize, dst_u, dst_v, width);
michael@0 1242 ARGBToYRow(row, dst_y, width);
michael@0 1243 ARGBToYRow(row + kRowSize, dst_y + dst_stride_y, width);
michael@0 1244 #endif
michael@0 1245 src_rgb565 += src_stride_rgb565 * 2;
michael@0 1246 dst_y += dst_stride_y * 2;
michael@0 1247 dst_u += dst_stride_u;
michael@0 1248 dst_v += dst_stride_v;
michael@0 1249 }
michael@0 1250 if (height & 1) {
michael@0 1251 #if defined(HAS_RGB565TOYROW_NEON)
michael@0 1252 RGB565ToUVRow(src_rgb565, 0, dst_u, dst_v, width);
michael@0 1253 RGB565ToYRow(src_rgb565, dst_y, width);
michael@0 1254 #else
michael@0 1255 RGB565ToARGBRow(src_rgb565, row, width);
michael@0 1256 ARGBToUVRow(row, 0, dst_u, dst_v, width);
michael@0 1257 ARGBToYRow(row, dst_y, width);
michael@0 1258 #endif
michael@0 1259 }
michael@0 1260 #if !defined(HAS_RGB565TOYROW_NEON)
michael@0 1261 free_aligned_buffer_64(row);
michael@0 1262 #endif
michael@0 1263 return 0;
michael@0 1264 }
michael@0 1265
michael@0 1266 // Convert ARGB1555 to I420.
michael@0 1267 LIBYUV_API
michael@0 1268 int ARGB1555ToI420(const uint8* src_argb1555, int src_stride_argb1555,
michael@0 1269 uint8* dst_y, int dst_stride_y,
michael@0 1270 uint8* dst_u, int dst_stride_u,
michael@0 1271 uint8* dst_v, int dst_stride_v,
michael@0 1272 int width, int height) {
michael@0 1273 if (!src_argb1555 || !dst_y || !dst_u || !dst_v ||
michael@0 1274 width <= 0 || height == 0) {
michael@0 1275 return -1;
michael@0 1276 }
michael@0 1277 // Negative height means invert the image.
michael@0 1278 if (height < 0) {
michael@0 1279 height = -height;
michael@0 1280 src_argb1555 = src_argb1555 + (height - 1) * src_stride_argb1555;
michael@0 1281 src_stride_argb1555 = -src_stride_argb1555;
michael@0 1282 }
michael@0 1283
michael@0 1284 #if defined(HAS_ARGB1555TOYROW_NEON)
michael@0 1285 void (*ARGB1555ToUVRow)(const uint8* src_argb1555, int src_stride_argb1555,
michael@0 1286 uint8* dst_u, uint8* dst_v, int width) = ARGB1555ToUVRow_C;
michael@0 1287 void (*ARGB1555ToYRow)(const uint8* src_argb1555, uint8* dst_y, int pix) =
michael@0 1288 ARGB1555ToYRow_C;
michael@0 1289 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
michael@0 1290 ARGB1555ToYRow = ARGB1555ToYRow_Any_NEON;
michael@0 1291 if (IS_ALIGNED(width, 8)) {
michael@0 1292 ARGB1555ToYRow = ARGB1555ToYRow_NEON;
michael@0 1293 }
michael@0 1294 if (width >= 16) {
michael@0 1295 ARGB1555ToUVRow = ARGB1555ToUVRow_Any_NEON;
michael@0 1296 if (IS_ALIGNED(width, 16)) {
michael@0 1297 ARGB1555ToUVRow = ARGB1555ToUVRow_NEON;
michael@0 1298 }
michael@0 1299 }
michael@0 1300 }
michael@0 1301 #else // HAS_ARGB1555TOYROW_NEON
michael@0 1302
michael@0 1303 // Allocate 2 rows of ARGB.
michael@0 1304 const int kRowSize = (width * 4 + 15) & ~15;
michael@0 1305 align_buffer_64(row, kRowSize * 2);
michael@0 1306
michael@0 1307 void (*ARGB1555ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) =
michael@0 1308 ARGB1555ToARGBRow_C;
michael@0 1309 #if defined(HAS_ARGB1555TOARGBROW_SSE2)
michael@0 1310 if (TestCpuFlag(kCpuHasSSE2) && width >= 8) {
michael@0 1311 ARGB1555ToARGBRow = ARGB1555ToARGBRow_Any_SSE2;
michael@0 1312 if (IS_ALIGNED(width, 8)) {
michael@0 1313 ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2;
michael@0 1314 }
michael@0 1315 }
michael@0 1316 #endif
michael@0 1317 void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb,
michael@0 1318 uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C;
michael@0 1319 #if defined(HAS_ARGBTOUVROW_SSSE3)
michael@0 1320 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
michael@0 1321 ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
michael@0 1322 if (IS_ALIGNED(width, 16)) {
michael@0 1323 ARGBToUVRow = ARGBToUVRow_SSSE3;
michael@0 1324 }
michael@0 1325 }
michael@0 1326 #endif
michael@0 1327 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
michael@0 1328 ARGBToYRow_C;
michael@0 1329 #if defined(HAS_ARGBTOUVROW_SSSE3)
michael@0 1330 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
michael@0 1331 ARGBToYRow = ARGBToYRow_Any_SSSE3;
michael@0 1332 if (IS_ALIGNED(width, 16)) {
michael@0 1333 ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
michael@0 1334 if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
michael@0 1335 ARGBToYRow = ARGBToYRow_SSSE3;
michael@0 1336 }
michael@0 1337 }
michael@0 1338 }
michael@0 1339 #endif // HAS_ARGBTOUVROW_SSSE3
michael@0 1340 #endif // HAS_ARGB1555TOYROW_NEON
michael@0 1341
michael@0 1342 for (int y = 0; y < height - 1; y += 2) {
michael@0 1343 #if defined(HAS_ARGB1555TOYROW_NEON)
michael@0 1344 ARGB1555ToUVRow(src_argb1555, src_stride_argb1555, dst_u, dst_v, width);
michael@0 1345 ARGB1555ToYRow(src_argb1555, dst_y, width);
michael@0 1346 ARGB1555ToYRow(src_argb1555 + src_stride_argb1555, dst_y + dst_stride_y,
michael@0 1347 width);
michael@0 1348 #else
michael@0 1349 ARGB1555ToARGBRow(src_argb1555, row, width);
michael@0 1350 ARGB1555ToARGBRow(src_argb1555 + src_stride_argb1555, row + kRowSize,
michael@0 1351 width);
michael@0 1352 ARGBToUVRow(row, kRowSize, dst_u, dst_v, width);
michael@0 1353 ARGBToYRow(row, dst_y, width);
michael@0 1354 ARGBToYRow(row + kRowSize, dst_y + dst_stride_y, width);
michael@0 1355 #endif
michael@0 1356 src_argb1555 += src_stride_argb1555 * 2;
michael@0 1357 dst_y += dst_stride_y * 2;
michael@0 1358 dst_u += dst_stride_u;
michael@0 1359 dst_v += dst_stride_v;
michael@0 1360 }
michael@0 1361 if (height & 1) {
michael@0 1362 #if defined(HAS_ARGB1555TOYROW_NEON)
michael@0 1363 ARGB1555ToUVRow(src_argb1555, 0, dst_u, dst_v, width);
michael@0 1364 ARGB1555ToYRow(src_argb1555, dst_y, width);
michael@0 1365 #else
michael@0 1366 ARGB1555ToARGBRow(src_argb1555, row, width);
michael@0 1367 ARGBToUVRow(row, 0, dst_u, dst_v, width);
michael@0 1368 ARGBToYRow(row, dst_y, width);
michael@0 1369 #endif
michael@0 1370 }
michael@0 1371 #if !defined(HAS_ARGB1555TOYROW_NEON)
michael@0 1372 free_aligned_buffer_64(row);
michael@0 1373 #endif
michael@0 1374 return 0;
michael@0 1375 }
michael@0 1376
michael@0 1377 // Convert ARGB4444 to I420.
michael@0 1378 LIBYUV_API
michael@0 1379 int ARGB4444ToI420(const uint8* src_argb4444, int src_stride_argb4444,
michael@0 1380 uint8* dst_y, int dst_stride_y,
michael@0 1381 uint8* dst_u, int dst_stride_u,
michael@0 1382 uint8* dst_v, int dst_stride_v,
michael@0 1383 int width, int height) {
michael@0 1384 if (!src_argb4444 || !dst_y || !dst_u || !dst_v ||
michael@0 1385 width <= 0 || height == 0) {
michael@0 1386 return -1;
michael@0 1387 }
michael@0 1388 // Negative height means invert the image.
michael@0 1389 if (height < 0) {
michael@0 1390 height = -height;
michael@0 1391 src_argb4444 = src_argb4444 + (height - 1) * src_stride_argb4444;
michael@0 1392 src_stride_argb4444 = -src_stride_argb4444;
michael@0 1393 }
michael@0 1394
michael@0 1395 #if defined(HAS_ARGB4444TOYROW_NEON)
michael@0 1396 void (*ARGB4444ToUVRow)(const uint8* src_argb4444, int src_stride_argb4444,
michael@0 1397 uint8* dst_u, uint8* dst_v, int width) = ARGB4444ToUVRow_C;
michael@0 1398 void (*ARGB4444ToYRow)(const uint8* src_argb4444, uint8* dst_y, int pix) =
michael@0 1399 ARGB4444ToYRow_C;
michael@0 1400 if (TestCpuFlag(kCpuHasNEON) && width >= 8) {
michael@0 1401 ARGB4444ToYRow = ARGB4444ToYRow_Any_NEON;
michael@0 1402 if (IS_ALIGNED(width, 8)) {
michael@0 1403 ARGB4444ToYRow = ARGB4444ToYRow_NEON;
michael@0 1404 }
michael@0 1405 if (width >= 16) {
michael@0 1406 ARGB4444ToUVRow = ARGB4444ToUVRow_Any_NEON;
michael@0 1407 if (IS_ALIGNED(width, 16)) {
michael@0 1408 ARGB4444ToUVRow = ARGB4444ToUVRow_NEON;
michael@0 1409 }
michael@0 1410 }
michael@0 1411 }
michael@0 1412 #else // HAS_ARGB4444TOYROW_NEON
michael@0 1413
michael@0 1414 // Allocate 2 rows of ARGB.
michael@0 1415 const int kRowSize = (width * 4 + 15) & ~15;
michael@0 1416 align_buffer_64(row, kRowSize * 2);
michael@0 1417
michael@0 1418 void (*ARGB4444ToARGBRow)(const uint8* src_rgb, uint8* dst_argb, int pix) =
michael@0 1419 ARGB4444ToARGBRow_C;
michael@0 1420 #if defined(HAS_ARGB4444TOARGBROW_SSE2)
michael@0 1421 if (TestCpuFlag(kCpuHasSSE2) && width >= 8) {
michael@0 1422 ARGB4444ToARGBRow = ARGB4444ToARGBRow_Any_SSE2;
michael@0 1423 if (IS_ALIGNED(width, 8)) {
michael@0 1424 ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2;
michael@0 1425 }
michael@0 1426 }
michael@0 1427 #endif
michael@0 1428 void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb,
michael@0 1429 uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C;
michael@0 1430 #if defined(HAS_ARGBTOUVROW_SSSE3)
michael@0 1431 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
michael@0 1432 ARGBToUVRow = ARGBToUVRow_Any_SSSE3;
michael@0 1433 if (IS_ALIGNED(width, 16)) {
michael@0 1434 ARGBToUVRow = ARGBToUVRow_SSSE3;
michael@0 1435 }
michael@0 1436 }
michael@0 1437 #endif
michael@0 1438 void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
michael@0 1439 ARGBToYRow_C;
michael@0 1440 #if defined(HAS_ARGBTOUVROW_SSSE3)
michael@0 1441 if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) {
michael@0 1442 ARGBToYRow = ARGBToYRow_Any_SSSE3;
michael@0 1443 if (IS_ALIGNED(width, 16)) {
michael@0 1444 ARGBToYRow = ARGBToYRow_Unaligned_SSSE3;
michael@0 1445 if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
michael@0 1446 ARGBToYRow = ARGBToYRow_SSSE3;
michael@0 1447 }
michael@0 1448 }
michael@0 1449 }
michael@0 1450 #endif // HAS_ARGBTOUVROW_SSSE3
michael@0 1451 #endif // HAS_ARGB4444TOYROW_NEON
michael@0 1452
michael@0 1453 for (int y = 0; y < height - 1; y += 2) {
michael@0 1454 #if defined(HAS_ARGB4444TOYROW_NEON)
michael@0 1455 ARGB4444ToUVRow(src_argb4444, src_stride_argb4444, dst_u, dst_v, width);
michael@0 1456 ARGB4444ToYRow(src_argb4444, dst_y, width);
michael@0 1457 ARGB4444ToYRow(src_argb4444 + src_stride_argb4444, dst_y + dst_stride_y,
michael@0 1458 width);
michael@0 1459 #else
michael@0 1460 ARGB4444ToARGBRow(src_argb4444, row, width);
michael@0 1461 ARGB4444ToARGBRow(src_argb4444 + src_stride_argb4444, row + kRowSize,
michael@0 1462 width);
michael@0 1463 ARGBToUVRow(row, kRowSize, dst_u, dst_v, width);
michael@0 1464 ARGBToYRow(row, dst_y, width);
michael@0 1465 ARGBToYRow(row + kRowSize, dst_y + dst_stride_y, width);
michael@0 1466 #endif
michael@0 1467 src_argb4444 += src_stride_argb4444 * 2;
michael@0 1468 dst_y += dst_stride_y * 2;
michael@0 1469 dst_u += dst_stride_u;
michael@0 1470 dst_v += dst_stride_v;
michael@0 1471 }
michael@0 1472 if (height & 1) {
michael@0 1473 #if defined(HAS_ARGB4444TOYROW_NEON)
michael@0 1474 ARGB4444ToUVRow(src_argb4444, 0, dst_u, dst_v, width);
michael@0 1475 ARGB4444ToYRow(src_argb4444, dst_y, width);
michael@0 1476 #else
michael@0 1477 ARGB4444ToARGBRow(src_argb4444, row, width);
michael@0 1478 ARGBToUVRow(row, 0, dst_u, dst_v, width);
michael@0 1479 ARGBToYRow(row, dst_y, width);
michael@0 1480 #endif
michael@0 1481 }
michael@0 1482 #if !defined(HAS_ARGB4444TOYROW_NEON)
michael@0 1483 free_aligned_buffer_64(row);
michael@0 1484 #endif
michael@0 1485 return 0;
michael@0 1486 }
michael@0 1487
michael@0 1488 #ifdef __cplusplus
michael@0 1489 } // extern "C"
michael@0 1490 } // namespace libyuv
michael@0 1491 #endif

mercurial