1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libyuv/source/convert_from_argb.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1096 @@ 1.4 +/* 1.5 + * Copyright 2012 The LibYuv Project Authors. All rights reserved. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license 1.8 + * that can be found in the LICENSE file in the root of the source 1.9 + * tree. An additional intellectual property rights grant can be found 1.10 + * in the file PATENTS. All contributing project authors may 1.11 + * be found in the AUTHORS file in the root of the source tree. 1.12 + */ 1.13 + 1.14 +#include "libyuv/convert_from_argb.h" 1.15 + 1.16 +#include "libyuv/basic_types.h" 1.17 +#include "libyuv/cpu_id.h" 1.18 +#include "libyuv/format_conversion.h" 1.19 +#include "libyuv/planar_functions.h" 1.20 +#include "libyuv/row.h" 1.21 + 1.22 +#ifdef __cplusplus 1.23 +namespace libyuv { 1.24 +extern "C" { 1.25 +#endif 1.26 + 1.27 +// ARGB little endian (bgra in memory) to I444 1.28 +LIBYUV_API 1.29 +int ARGBToI444(const uint8* src_argb, int src_stride_argb, 1.30 + uint8* dst_y, int dst_stride_y, 1.31 + uint8* dst_u, int dst_stride_u, 1.32 + uint8* dst_v, int dst_stride_v, 1.33 + int width, int height) { 1.34 + if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) { 1.35 + return -1; 1.36 + } 1.37 + if (height < 0) { 1.38 + height = -height; 1.39 + src_argb = src_argb + (height - 1) * src_stride_argb; 1.40 + src_stride_argb = -src_stride_argb; 1.41 + } 1.42 + // Coalesce rows. 1.43 + if (src_stride_argb == width * 4 && 1.44 + dst_stride_y == width && 1.45 + dst_stride_u == width && 1.46 + dst_stride_v == width) { 1.47 + width *= height; 1.48 + height = 1; 1.49 + src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0; 1.50 + } 1.51 + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = 1.52 + ARGBToYRow_C; 1.53 + void (*ARGBToUV444Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v, 1.54 + int pix) = ARGBToUV444Row_C; 1.55 +#if defined(HAS_ARGBTOUV444ROW_SSSE3) 1.56 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { 1.57 + ARGBToUV444Row = ARGBToUV444Row_Any_SSSE3; 1.58 + if (IS_ALIGNED(width, 16)) { 1.59 + ARGBToUV444Row = ARGBToUV444Row_Unaligned_SSSE3; 1.60 + if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { 1.61 + ARGBToUV444Row = ARGBToUV444Row_SSSE3; 1.62 + } 1.63 + } 1.64 + } 1.65 +#endif 1.66 +#if defined(HAS_ARGBTOYROW_SSSE3) 1.67 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { 1.68 + ARGBToYRow = ARGBToYRow_Any_SSSE3; 1.69 + if (IS_ALIGNED(width, 16)) { 1.70 + ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; 1.71 + if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && 1.72 + IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { 1.73 + ARGBToYRow = ARGBToYRow_SSSE3; 1.74 + } 1.75 + } 1.76 + } 1.77 + 1.78 +#elif defined(HAS_ARGBTOYROW_NEON) 1.79 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.80 + ARGBToYRow = ARGBToYRow_Any_NEON; 1.81 + ARGBToUV444Row = ARGBToUV444Row_Any_NEON; 1.82 + if (IS_ALIGNED(width, 8)) { 1.83 + ARGBToYRow = ARGBToYRow_NEON; 1.84 + ARGBToUV444Row = ARGBToUV444Row_NEON; 1.85 + } 1.86 + } 1.87 +#endif 1.88 + 1.89 + for (int y = 0; y < height; ++y) { 1.90 + ARGBToUV444Row(src_argb, dst_u, dst_v, width); 1.91 + ARGBToYRow(src_argb, dst_y, width); 1.92 + src_argb += src_stride_argb; 1.93 + dst_y += dst_stride_y; 1.94 + dst_u += dst_stride_u; 1.95 + dst_v += dst_stride_v; 1.96 + } 1.97 + return 0; 1.98 +} 1.99 + 1.100 +// ARGB little endian (bgra in memory) to I422 1.101 +LIBYUV_API 1.102 +int ARGBToI422(const uint8* src_argb, int src_stride_argb, 1.103 + uint8* dst_y, int dst_stride_y, 1.104 + uint8* dst_u, int dst_stride_u, 1.105 + uint8* dst_v, int dst_stride_v, 1.106 + int width, int height) { 1.107 + if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) { 1.108 + return -1; 1.109 + } 1.110 + if (height < 0) { 1.111 + height = -height; 1.112 + src_argb = src_argb + (height - 1) * src_stride_argb; 1.113 + src_stride_argb = -src_stride_argb; 1.114 + } 1.115 + // Coalesce rows. 1.116 + if (src_stride_argb == width * 4 && 1.117 + dst_stride_y == width && 1.118 + dst_stride_u * 2 == width && 1.119 + dst_stride_v * 2 == width) { 1.120 + width *= height; 1.121 + height = 1; 1.122 + src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0; 1.123 + } 1.124 + void (*ARGBToUV422Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v, 1.125 + int pix) = ARGBToUV422Row_C; 1.126 +#if defined(HAS_ARGBTOUV422ROW_SSSE3) 1.127 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { 1.128 + ARGBToUV422Row = ARGBToUV422Row_Any_SSSE3; 1.129 + if (IS_ALIGNED(width, 16)) { 1.130 + ARGBToUV422Row = ARGBToUV422Row_Unaligned_SSSE3; 1.131 + if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { 1.132 + ARGBToUV422Row = ARGBToUV422Row_SSSE3; 1.133 + } 1.134 + } 1.135 + } 1.136 +#endif 1.137 + 1.138 + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = 1.139 + ARGBToYRow_C; 1.140 +#if defined(HAS_ARGBTOYROW_SSSE3) 1.141 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { 1.142 + ARGBToYRow = ARGBToYRow_Any_SSSE3; 1.143 + if (IS_ALIGNED(width, 16)) { 1.144 + ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; 1.145 + if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && 1.146 + IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { 1.147 + ARGBToYRow = ARGBToYRow_SSSE3; 1.148 + } 1.149 + } 1.150 + } 1.151 +#elif defined(HAS_ARGBTOYROW_NEON) 1.152 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.153 + ARGBToYRow = ARGBToYRow_Any_NEON; 1.154 + if (IS_ALIGNED(width, 8)) { 1.155 + ARGBToYRow = ARGBToYRow_NEON; 1.156 + } 1.157 + if (width >= 16) { 1.158 + ARGBToUV422Row = ARGBToUV422Row_Any_NEON; 1.159 + if (IS_ALIGNED(width, 16)) { 1.160 + ARGBToUV422Row = ARGBToUV422Row_NEON; 1.161 + } 1.162 + } 1.163 + } 1.164 +#endif 1.165 + 1.166 + for (int y = 0; y < height; ++y) { 1.167 + ARGBToUV422Row(src_argb, dst_u, dst_v, width); 1.168 + ARGBToYRow(src_argb, dst_y, width); 1.169 + src_argb += src_stride_argb; 1.170 + dst_y += dst_stride_y; 1.171 + dst_u += dst_stride_u; 1.172 + dst_v += dst_stride_v; 1.173 + } 1.174 + return 0; 1.175 +} 1.176 + 1.177 +// ARGB little endian (bgra in memory) to I411 1.178 +LIBYUV_API 1.179 +int ARGBToI411(const uint8* src_argb, int src_stride_argb, 1.180 + uint8* dst_y, int dst_stride_y, 1.181 + uint8* dst_u, int dst_stride_u, 1.182 + uint8* dst_v, int dst_stride_v, 1.183 + int width, int height) { 1.184 + if (!src_argb || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0) { 1.185 + return -1; 1.186 + } 1.187 + if (height < 0) { 1.188 + height = -height; 1.189 + src_argb = src_argb + (height - 1) * src_stride_argb; 1.190 + src_stride_argb = -src_stride_argb; 1.191 + } 1.192 + // Coalesce rows. 1.193 + if (src_stride_argb == width * 4 && 1.194 + dst_stride_y == width && 1.195 + dst_stride_u * 4 == width && 1.196 + dst_stride_v * 4 == width) { 1.197 + width *= height; 1.198 + height = 1; 1.199 + src_stride_argb = dst_stride_y = dst_stride_u = dst_stride_v = 0; 1.200 + } 1.201 + void (*ARGBToUV411Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v, 1.202 + int pix) = ARGBToUV411Row_C; 1.203 + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = 1.204 + ARGBToYRow_C; 1.205 +#if defined(HAS_ARGBTOYROW_SSSE3) 1.206 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { 1.207 + ARGBToYRow = ARGBToYRow_Any_SSSE3; 1.208 + if (IS_ALIGNED(width, 16)) { 1.209 + ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; 1.210 + if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && 1.211 + IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { 1.212 + ARGBToYRow = ARGBToYRow_SSSE3; 1.213 + } 1.214 + } 1.215 + } 1.216 +#endif 1.217 +#if defined(HAS_ARGBTOYROW_AVX2) 1.218 + if (TestCpuFlag(kCpuHasAVX2) && width >= 32) { 1.219 + ARGBToYRow = ARGBToYRow_Any_AVX2; 1.220 + if (IS_ALIGNED(width, 32)) { 1.221 + ARGBToYRow = ARGBToYRow_AVX2; 1.222 + } 1.223 + } 1.224 +#endif 1.225 +#if defined(HAS_ARGBTOYROW_NEON) 1.226 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.227 + ARGBToYRow = ARGBToYRow_Any_NEON; 1.228 + if (IS_ALIGNED(width, 8)) { 1.229 + ARGBToYRow = ARGBToYRow_NEON; 1.230 + } 1.231 + if (width >= 32) { 1.232 + ARGBToUV411Row = ARGBToUV411Row_Any_NEON; 1.233 + if (IS_ALIGNED(width, 32)) { 1.234 + ARGBToUV411Row = ARGBToUV411Row_NEON; 1.235 + } 1.236 + } 1.237 + } 1.238 +#endif 1.239 + 1.240 + for (int y = 0; y < height; ++y) { 1.241 + ARGBToUV411Row(src_argb, dst_u, dst_v, width); 1.242 + ARGBToYRow(src_argb, dst_y, width); 1.243 + src_argb += src_stride_argb; 1.244 + dst_y += dst_stride_y; 1.245 + dst_u += dst_stride_u; 1.246 + dst_v += dst_stride_v; 1.247 + } 1.248 + return 0; 1.249 +} 1.250 + 1.251 +LIBYUV_API 1.252 +int ARGBToNV12(const uint8* src_argb, int src_stride_argb, 1.253 + uint8* dst_y, int dst_stride_y, 1.254 + uint8* dst_uv, int dst_stride_uv, 1.255 + int width, int height) { 1.256 + if (!src_argb || 1.257 + !dst_y || !dst_uv || 1.258 + width <= 0 || height == 0) { 1.259 + return -1; 1.260 + } 1.261 + // Negative height means invert the image. 1.262 + if (height < 0) { 1.263 + height = -height; 1.264 + src_argb = src_argb + (height - 1) * src_stride_argb; 1.265 + src_stride_argb = -src_stride_argb; 1.266 + } 1.267 + void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, 1.268 + uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C; 1.269 + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = 1.270 + ARGBToYRow_C; 1.271 +#if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3) 1.272 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { 1.273 + ARGBToUVRow = ARGBToUVRow_Any_SSSE3; 1.274 + ARGBToYRow = ARGBToYRow_Any_SSSE3; 1.275 + if (IS_ALIGNED(width, 16)) { 1.276 + ARGBToUVRow = ARGBToUVRow_Unaligned_SSSE3; 1.277 + ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; 1.278 + if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { 1.279 + ARGBToUVRow = ARGBToUVRow_SSSE3; 1.280 + if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { 1.281 + ARGBToYRow = ARGBToYRow_SSSE3; 1.282 + } 1.283 + } 1.284 + } 1.285 + } 1.286 +#elif defined(HAS_ARGBTOYROW_NEON) 1.287 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.288 + ARGBToYRow = ARGBToYRow_Any_NEON; 1.289 + if (IS_ALIGNED(width, 8)) { 1.290 + ARGBToYRow = ARGBToYRow_NEON; 1.291 + } 1.292 + if (width >= 16) { 1.293 + ARGBToUVRow = ARGBToUVRow_Any_NEON; 1.294 + if (IS_ALIGNED(width, 16)) { 1.295 + ARGBToUVRow = ARGBToUVRow_NEON; 1.296 + } 1.297 + } 1.298 + } 1.299 +#endif 1.300 + int halfwidth = (width + 1) >> 1; 1.301 + void (*MergeUVRow_)(const uint8* src_u, const uint8* src_v, uint8* dst_uv, 1.302 + int width) = MergeUVRow_C; 1.303 +#if defined(HAS_MERGEUVROW_SSE2) 1.304 + if (TestCpuFlag(kCpuHasSSE2) && halfwidth >= 16) { 1.305 + MergeUVRow_ = MergeUVRow_Any_SSE2; 1.306 + if (IS_ALIGNED(halfwidth, 16)) { 1.307 + MergeUVRow_ = MergeUVRow_Unaligned_SSE2; 1.308 + if (IS_ALIGNED(dst_uv, 16) && IS_ALIGNED(dst_stride_uv, 16)) { 1.309 + MergeUVRow_ = MergeUVRow_SSE2; 1.310 + } 1.311 + } 1.312 + } 1.313 +#endif 1.314 +#if defined(HAS_MERGEUVROW_AVX2) 1.315 + if (TestCpuFlag(kCpuHasAVX2) && halfwidth >= 32) { 1.316 + MergeUVRow_ = MergeUVRow_Any_AVX2; 1.317 + if (IS_ALIGNED(halfwidth, 32)) { 1.318 + MergeUVRow_ = MergeUVRow_AVX2; 1.319 + } 1.320 + } 1.321 +#endif 1.322 +#if defined(HAS_MERGEUVROW_NEON) 1.323 + if (TestCpuFlag(kCpuHasNEON) && halfwidth >= 16) { 1.324 + MergeUVRow_ = MergeUVRow_Any_NEON; 1.325 + if (IS_ALIGNED(halfwidth, 16)) { 1.326 + MergeUVRow_ = MergeUVRow_NEON; 1.327 + } 1.328 + } 1.329 +#endif 1.330 + 1.331 + // Allocate a rows of uv. 1.332 + align_buffer_64(row_u, ((halfwidth + 15) & ~15) * 2); 1.333 + uint8* row_v = row_u + ((halfwidth + 15) & ~15); 1.334 + 1.335 + for (int y = 0; y < height - 1; y += 2) { 1.336 + ARGBToUVRow(src_argb, src_stride_argb, row_u, row_v, width); 1.337 + MergeUVRow_(row_u, row_v, dst_uv, halfwidth); 1.338 + ARGBToYRow(src_argb, dst_y, width); 1.339 + ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width); 1.340 + src_argb += src_stride_argb * 2; 1.341 + dst_y += dst_stride_y * 2; 1.342 + dst_uv += dst_stride_uv; 1.343 + } 1.344 + if (height & 1) { 1.345 + ARGBToUVRow(src_argb, 0, row_u, row_v, width); 1.346 + MergeUVRow_(row_u, row_v, dst_uv, halfwidth); 1.347 + ARGBToYRow(src_argb, dst_y, width); 1.348 + } 1.349 + free_aligned_buffer_64(row_u); 1.350 + return 0; 1.351 +} 1.352 + 1.353 +// Same as NV12 but U and V swapped. 1.354 +LIBYUV_API 1.355 +int ARGBToNV21(const uint8* src_argb, int src_stride_argb, 1.356 + uint8* dst_y, int dst_stride_y, 1.357 + uint8* dst_uv, int dst_stride_uv, 1.358 + int width, int height) { 1.359 + if (!src_argb || 1.360 + !dst_y || !dst_uv || 1.361 + width <= 0 || height == 0) { 1.362 + return -1; 1.363 + } 1.364 + // Negative height means invert the image. 1.365 + if (height < 0) { 1.366 + height = -height; 1.367 + src_argb = src_argb + (height - 1) * src_stride_argb; 1.368 + src_stride_argb = -src_stride_argb; 1.369 + } 1.370 + void (*ARGBToUVRow)(const uint8* src_argb0, int src_stride_argb, 1.371 + uint8* dst_u, uint8* dst_v, int width) = ARGBToUVRow_C; 1.372 + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = 1.373 + ARGBToYRow_C; 1.374 +#if defined(HAS_ARGBTOYROW_SSSE3) && defined(HAS_ARGBTOUVROW_SSSE3) 1.375 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { 1.376 + ARGBToUVRow = ARGBToUVRow_Any_SSSE3; 1.377 + ARGBToYRow = ARGBToYRow_Any_SSSE3; 1.378 + if (IS_ALIGNED(width, 16)) { 1.379 + ARGBToUVRow = ARGBToUVRow_Unaligned_SSSE3; 1.380 + ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; 1.381 + if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { 1.382 + ARGBToUVRow = ARGBToUVRow_SSSE3; 1.383 + if (IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { 1.384 + ARGBToYRow = ARGBToYRow_SSSE3; 1.385 + } 1.386 + } 1.387 + } 1.388 + } 1.389 +#elif defined(HAS_ARGBTOYROW_NEON) 1.390 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.391 + ARGBToYRow = ARGBToYRow_Any_NEON; 1.392 + if (IS_ALIGNED(width, 8)) { 1.393 + ARGBToYRow = ARGBToYRow_NEON; 1.394 + } 1.395 + if (width >= 16) { 1.396 + ARGBToUVRow = ARGBToUVRow_Any_NEON; 1.397 + if (IS_ALIGNED(width, 16)) { 1.398 + ARGBToUVRow = ARGBToUVRow_NEON; 1.399 + } 1.400 + } 1.401 + } 1.402 +#endif 1.403 + int halfwidth = (width + 1) >> 1; 1.404 + void (*MergeUVRow_)(const uint8* src_u, const uint8* src_v, uint8* dst_uv, 1.405 + int width) = MergeUVRow_C; 1.406 +#if defined(HAS_MERGEUVROW_SSE2) 1.407 + if (TestCpuFlag(kCpuHasSSE2) && halfwidth >= 16) { 1.408 + MergeUVRow_ = MergeUVRow_Any_SSE2; 1.409 + if (IS_ALIGNED(halfwidth, 16)) { 1.410 + MergeUVRow_ = MergeUVRow_Unaligned_SSE2; 1.411 + if (IS_ALIGNED(dst_uv, 16) && IS_ALIGNED(dst_stride_uv, 16)) { 1.412 + MergeUVRow_ = MergeUVRow_SSE2; 1.413 + } 1.414 + } 1.415 + } 1.416 +#endif 1.417 +#if defined(HAS_MERGEUVROW_AVX2) 1.418 + if (TestCpuFlag(kCpuHasAVX2) && halfwidth >= 32) { 1.419 + MergeUVRow_ = MergeUVRow_Any_AVX2; 1.420 + if (IS_ALIGNED(halfwidth, 32)) { 1.421 + MergeUVRow_ = MergeUVRow_AVX2; 1.422 + } 1.423 + } 1.424 +#endif 1.425 +#if defined(HAS_MERGEUVROW_NEON) 1.426 + if (TestCpuFlag(kCpuHasNEON) && halfwidth >= 16) { 1.427 + MergeUVRow_ = MergeUVRow_Any_NEON; 1.428 + if (IS_ALIGNED(halfwidth, 16)) { 1.429 + MergeUVRow_ = MergeUVRow_NEON; 1.430 + } 1.431 + } 1.432 +#endif 1.433 + 1.434 + // Allocate a rows of uv. 1.435 + align_buffer_64(row_u, ((halfwidth + 15) & ~15) * 2); 1.436 + uint8* row_v = row_u + ((halfwidth + 15) & ~15); 1.437 + 1.438 + for (int y = 0; y < height - 1; y += 2) { 1.439 + ARGBToUVRow(src_argb, src_stride_argb, row_u, row_v, width); 1.440 + MergeUVRow_(row_v, row_u, dst_uv, halfwidth); 1.441 + ARGBToYRow(src_argb, dst_y, width); 1.442 + ARGBToYRow(src_argb + src_stride_argb, dst_y + dst_stride_y, width); 1.443 + src_argb += src_stride_argb * 2; 1.444 + dst_y += dst_stride_y * 2; 1.445 + dst_uv += dst_stride_uv; 1.446 + } 1.447 + if (height & 1) { 1.448 + ARGBToUVRow(src_argb, 0, row_u, row_v, width); 1.449 + MergeUVRow_(row_v, row_u, dst_uv, halfwidth); 1.450 + ARGBToYRow(src_argb, dst_y, width); 1.451 + } 1.452 + free_aligned_buffer_64(row_u); 1.453 + return 0; 1.454 +} 1.455 + 1.456 +// Convert ARGB to YUY2. 1.457 +LIBYUV_API 1.458 +int ARGBToYUY2(const uint8* src_argb, int src_stride_argb, 1.459 + uint8* dst_yuy2, int dst_stride_yuy2, 1.460 + int width, int height) { 1.461 + if (!src_argb || !dst_yuy2 || 1.462 + width <= 0 || height == 0) { 1.463 + return -1; 1.464 + } 1.465 + // Negative height means invert the image. 1.466 + if (height < 0) { 1.467 + height = -height; 1.468 + dst_yuy2 = dst_yuy2 + (height - 1) * dst_stride_yuy2; 1.469 + dst_stride_yuy2 = -dst_stride_yuy2; 1.470 + } 1.471 + // Coalesce rows. 1.472 + if (src_stride_argb == width * 4 && 1.473 + dst_stride_yuy2 == width * 2) { 1.474 + width *= height; 1.475 + height = 1; 1.476 + src_stride_argb = dst_stride_yuy2 = 0; 1.477 + } 1.478 + void (*ARGBToUV422Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v, 1.479 + int pix) = ARGBToUV422Row_C; 1.480 +#if defined(HAS_ARGBTOUV422ROW_SSSE3) 1.481 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { 1.482 + ARGBToUV422Row = ARGBToUV422Row_Any_SSSE3; 1.483 + if (IS_ALIGNED(width, 16)) { 1.484 + ARGBToUV422Row = ARGBToUV422Row_Unaligned_SSSE3; 1.485 + if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { 1.486 + ARGBToUV422Row = ARGBToUV422Row_SSSE3; 1.487 + } 1.488 + } 1.489 + } 1.490 +#endif 1.491 + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = 1.492 + ARGBToYRow_C; 1.493 +#if defined(HAS_ARGBTOYROW_SSSE3) 1.494 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { 1.495 + ARGBToYRow = ARGBToYRow_Any_SSSE3; 1.496 + if (IS_ALIGNED(width, 16)) { 1.497 + ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; 1.498 + if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { 1.499 + ARGBToYRow = ARGBToYRow_SSSE3; 1.500 + } 1.501 + } 1.502 + } 1.503 +#elif defined(HAS_ARGBTOYROW_NEON) 1.504 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.505 + ARGBToYRow = ARGBToYRow_Any_NEON; 1.506 + if (IS_ALIGNED(width, 8)) { 1.507 + ARGBToYRow = ARGBToYRow_NEON; 1.508 + } 1.509 + if (width >= 16) { 1.510 + ARGBToUV422Row = ARGBToUV422Row_Any_NEON; 1.511 + if (IS_ALIGNED(width, 16)) { 1.512 + ARGBToUV422Row = ARGBToUV422Row_NEON; 1.513 + } 1.514 + } 1.515 + } 1.516 +#endif 1.517 + 1.518 + void (*I422ToYUY2Row)(const uint8* src_y, const uint8* src_u, 1.519 + const uint8* src_v, uint8* dst_yuy2, int width) = 1.520 + I422ToYUY2Row_C; 1.521 +#if defined(HAS_I422TOYUY2ROW_SSE2) 1.522 + if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { 1.523 + I422ToYUY2Row = I422ToYUY2Row_Any_SSE2; 1.524 + if (IS_ALIGNED(width, 16)) { 1.525 + I422ToYUY2Row = I422ToYUY2Row_SSE2; 1.526 + } 1.527 + } 1.528 +#elif defined(HAS_I422TOYUY2ROW_NEON) 1.529 + if (TestCpuFlag(kCpuHasNEON) && width >= 16) { 1.530 + I422ToYUY2Row = I422ToYUY2Row_Any_NEON; 1.531 + if (IS_ALIGNED(width, 16)) { 1.532 + I422ToYUY2Row = I422ToYUY2Row_NEON; 1.533 + } 1.534 + } 1.535 +#endif 1.536 + 1.537 + // Allocate a rows of yuv. 1.538 + align_buffer_64(row_y, ((width + 63) & ~63) * 2); 1.539 + uint8* row_u = row_y + ((width + 63) & ~63); 1.540 + uint8* row_v = row_u + ((width + 63) & ~63) / 2; 1.541 + 1.542 + for (int y = 0; y < height; ++y) { 1.543 + ARGBToUV422Row(src_argb, row_u, row_v, width); 1.544 + ARGBToYRow(src_argb, row_y, width); 1.545 + I422ToYUY2Row(row_y, row_u, row_v, dst_yuy2, width); 1.546 + src_argb += src_stride_argb; 1.547 + dst_yuy2 += dst_stride_yuy2; 1.548 + } 1.549 + 1.550 + free_aligned_buffer_64(row_y); 1.551 + return 0; 1.552 +} 1.553 + 1.554 +// Convert ARGB to UYVY. 1.555 +LIBYUV_API 1.556 +int ARGBToUYVY(const uint8* src_argb, int src_stride_argb, 1.557 + uint8* dst_uyvy, int dst_stride_uyvy, 1.558 + int width, int height) { 1.559 + if (!src_argb || !dst_uyvy || 1.560 + width <= 0 || height == 0) { 1.561 + return -1; 1.562 + } 1.563 + // Negative height means invert the image. 1.564 + if (height < 0) { 1.565 + height = -height; 1.566 + dst_uyvy = dst_uyvy + (height - 1) * dst_stride_uyvy; 1.567 + dst_stride_uyvy = -dst_stride_uyvy; 1.568 + } 1.569 + // Coalesce rows. 1.570 + if (src_stride_argb == width * 4 && 1.571 + dst_stride_uyvy == width * 2) { 1.572 + width *= height; 1.573 + height = 1; 1.574 + src_stride_argb = dst_stride_uyvy = 0; 1.575 + } 1.576 + void (*ARGBToUV422Row)(const uint8* src_argb, uint8* dst_u, uint8* dst_v, 1.577 + int pix) = ARGBToUV422Row_C; 1.578 +#if defined(HAS_ARGBTOUV422ROW_SSSE3) 1.579 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { 1.580 + ARGBToUV422Row = ARGBToUV422Row_Any_SSSE3; 1.581 + if (IS_ALIGNED(width, 16)) { 1.582 + ARGBToUV422Row = ARGBToUV422Row_Unaligned_SSSE3; 1.583 + if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { 1.584 + ARGBToUV422Row = ARGBToUV422Row_SSSE3; 1.585 + } 1.586 + } 1.587 + } 1.588 +#endif 1.589 + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = 1.590 + ARGBToYRow_C; 1.591 +#if defined(HAS_ARGBTOYROW_SSSE3) 1.592 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { 1.593 + ARGBToYRow = ARGBToYRow_Any_SSSE3; 1.594 + if (IS_ALIGNED(width, 16)) { 1.595 + ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; 1.596 + if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { 1.597 + ARGBToYRow = ARGBToYRow_SSSE3; 1.598 + } 1.599 + } 1.600 + } 1.601 +#elif defined(HAS_ARGBTOYROW_NEON) 1.602 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.603 + ARGBToYRow = ARGBToYRow_Any_NEON; 1.604 + if (IS_ALIGNED(width, 8)) { 1.605 + ARGBToYRow = ARGBToYRow_NEON; 1.606 + } 1.607 + if (width >= 16) { 1.608 + ARGBToUV422Row = ARGBToUV422Row_Any_NEON; 1.609 + if (IS_ALIGNED(width, 16)) { 1.610 + ARGBToUV422Row = ARGBToUV422Row_NEON; 1.611 + } 1.612 + } 1.613 + } 1.614 +#endif 1.615 + 1.616 + void (*I422ToUYVYRow)(const uint8* src_y, const uint8* src_u, 1.617 + const uint8* src_v, uint8* dst_uyvy, int width) = 1.618 + I422ToUYVYRow_C; 1.619 +#if defined(HAS_I422TOUYVYROW_SSE2) 1.620 + if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { 1.621 + I422ToUYVYRow = I422ToUYVYRow_Any_SSE2; 1.622 + if (IS_ALIGNED(width, 16)) { 1.623 + I422ToUYVYRow = I422ToUYVYRow_SSE2; 1.624 + } 1.625 + } 1.626 +#elif defined(HAS_I422TOUYVYROW_NEON) 1.627 + if (TestCpuFlag(kCpuHasNEON) && width >= 16) { 1.628 + I422ToUYVYRow = I422ToUYVYRow_Any_NEON; 1.629 + if (IS_ALIGNED(width, 16)) { 1.630 + I422ToUYVYRow = I422ToUYVYRow_NEON; 1.631 + } 1.632 + } 1.633 +#endif 1.634 + 1.635 + // Allocate a rows of yuv. 1.636 + align_buffer_64(row_y, ((width + 63) & ~63) * 2); 1.637 + uint8* row_u = row_y + ((width + 63) & ~63); 1.638 + uint8* row_v = row_u + ((width + 63) & ~63) / 2; 1.639 + 1.640 + for (int y = 0; y < height; ++y) { 1.641 + ARGBToUV422Row(src_argb, row_u, row_v, width); 1.642 + ARGBToYRow(src_argb, row_y, width); 1.643 + I422ToUYVYRow(row_y, row_u, row_v, dst_uyvy, width); 1.644 + src_argb += src_stride_argb; 1.645 + dst_uyvy += dst_stride_uyvy; 1.646 + } 1.647 + 1.648 + free_aligned_buffer_64(row_y); 1.649 + return 0; 1.650 +} 1.651 + 1.652 +// Convert ARGB to I400. 1.653 +LIBYUV_API 1.654 +int ARGBToI400(const uint8* src_argb, int src_stride_argb, 1.655 + uint8* dst_y, int dst_stride_y, 1.656 + int width, int height) { 1.657 + if (!src_argb || !dst_y || width <= 0 || height == 0) { 1.658 + return -1; 1.659 + } 1.660 + if (height < 0) { 1.661 + height = -height; 1.662 + src_argb = src_argb + (height - 1) * src_stride_argb; 1.663 + src_stride_argb = -src_stride_argb; 1.664 + } 1.665 + // Coalesce rows. 1.666 + if (src_stride_argb == width * 4 && 1.667 + dst_stride_y == width) { 1.668 + width *= height; 1.669 + height = 1; 1.670 + src_stride_argb = dst_stride_y = 0; 1.671 + } 1.672 + void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) = 1.673 + ARGBToYRow_C; 1.674 +#if defined(HAS_ARGBTOYROW_SSSE3) 1.675 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { 1.676 + ARGBToYRow = ARGBToYRow_Any_SSSE3; 1.677 + if (IS_ALIGNED(width, 16)) { 1.678 + ARGBToYRow = ARGBToYRow_Unaligned_SSSE3; 1.679 + if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && 1.680 + IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) { 1.681 + ARGBToYRow = ARGBToYRow_SSSE3; 1.682 + } 1.683 + } 1.684 + } 1.685 +#endif 1.686 +#if defined(HAS_ARGBTOYROW_AVX2) 1.687 + if (TestCpuFlag(kCpuHasAVX2) && width >= 32) { 1.688 + ARGBToYRow = ARGBToYRow_Any_AVX2; 1.689 + if (IS_ALIGNED(width, 32)) { 1.690 + ARGBToYRow = ARGBToYRow_AVX2; 1.691 + } 1.692 + } 1.693 +#endif 1.694 +#if defined(HAS_ARGBTOYROW_NEON) 1.695 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.696 + ARGBToYRow = ARGBToYRow_Any_NEON; 1.697 + if (IS_ALIGNED(width, 8)) { 1.698 + ARGBToYRow = ARGBToYRow_NEON; 1.699 + } 1.700 + } 1.701 +#endif 1.702 + 1.703 + for (int y = 0; y < height; ++y) { 1.704 + ARGBToYRow(src_argb, dst_y, width); 1.705 + src_argb += src_stride_argb; 1.706 + dst_y += dst_stride_y; 1.707 + } 1.708 + return 0; 1.709 +} 1.710 + 1.711 +// Shuffle table for converting ARGB to RGBA. 1.712 +static uvec8 kShuffleMaskARGBToRGBA = { 1.713 + 3u, 0u, 1u, 2u, 7u, 4u, 5u, 6u, 11u, 8u, 9u, 10u, 15u, 12u, 13u, 14u 1.714 +}; 1.715 + 1.716 +// Convert ARGB to RGBA. 1.717 +LIBYUV_API 1.718 +int ARGBToRGBA(const uint8* src_argb, int src_stride_argb, 1.719 + uint8* dst_rgba, int dst_stride_rgba, 1.720 + int width, int height) { 1.721 + return ARGBShuffle(src_argb, src_stride_argb, 1.722 + dst_rgba, dst_stride_rgba, 1.723 + (const uint8*)(&kShuffleMaskARGBToRGBA), 1.724 + width, height); 1.725 +} 1.726 + 1.727 +// Convert ARGB To RGB24. 1.728 +LIBYUV_API 1.729 +int ARGBToRGB24(const uint8* src_argb, int src_stride_argb, 1.730 + uint8* dst_rgb24, int dst_stride_rgb24, 1.731 + int width, int height) { 1.732 + if (!src_argb || !dst_rgb24 || width <= 0 || height == 0) { 1.733 + return -1; 1.734 + } 1.735 + if (height < 0) { 1.736 + height = -height; 1.737 + src_argb = src_argb + (height - 1) * src_stride_argb; 1.738 + src_stride_argb = -src_stride_argb; 1.739 + } 1.740 + // Coalesce rows. 1.741 + if (src_stride_argb == width * 4 && 1.742 + dst_stride_rgb24 == width * 3) { 1.743 + width *= height; 1.744 + height = 1; 1.745 + src_stride_argb = dst_stride_rgb24 = 0; 1.746 + } 1.747 + void (*ARGBToRGB24Row)(const uint8* src_argb, uint8* dst_rgb, int pix) = 1.748 + ARGBToRGB24Row_C; 1.749 +#if defined(HAS_ARGBTORGB24ROW_SSSE3) 1.750 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { 1.751 + ARGBToRGB24Row = ARGBToRGB24Row_Any_SSSE3; 1.752 + if (IS_ALIGNED(width, 16)) { 1.753 + ARGBToRGB24Row = ARGBToRGB24Row_SSSE3; 1.754 + } 1.755 + } 1.756 +#elif defined(HAS_ARGBTORGB24ROW_NEON) 1.757 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.758 + ARGBToRGB24Row = ARGBToRGB24Row_Any_NEON; 1.759 + if (IS_ALIGNED(width, 8)) { 1.760 + ARGBToRGB24Row = ARGBToRGB24Row_NEON; 1.761 + } 1.762 + } 1.763 +#endif 1.764 + 1.765 + for (int y = 0; y < height; ++y) { 1.766 + ARGBToRGB24Row(src_argb, dst_rgb24, width); 1.767 + src_argb += src_stride_argb; 1.768 + dst_rgb24 += dst_stride_rgb24; 1.769 + } 1.770 + return 0; 1.771 +} 1.772 + 1.773 +// Convert ARGB To RAW. 1.774 +LIBYUV_API 1.775 +int ARGBToRAW(const uint8* src_argb, int src_stride_argb, 1.776 + uint8* dst_raw, int dst_stride_raw, 1.777 + int width, int height) { 1.778 + if (!src_argb || !dst_raw || width <= 0 || height == 0) { 1.779 + return -1; 1.780 + } 1.781 + if (height < 0) { 1.782 + height = -height; 1.783 + src_argb = src_argb + (height - 1) * src_stride_argb; 1.784 + src_stride_argb = -src_stride_argb; 1.785 + } 1.786 + // Coalesce rows. 1.787 + if (src_stride_argb == width * 4 && 1.788 + dst_stride_raw == width * 3) { 1.789 + width *= height; 1.790 + height = 1; 1.791 + src_stride_argb = dst_stride_raw = 0; 1.792 + } 1.793 + void (*ARGBToRAWRow)(const uint8* src_argb, uint8* dst_rgb, int pix) = 1.794 + ARGBToRAWRow_C; 1.795 +#if defined(HAS_ARGBTORAWROW_SSSE3) 1.796 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { 1.797 + ARGBToRAWRow = ARGBToRAWRow_Any_SSSE3; 1.798 + if (IS_ALIGNED(width, 16)) { 1.799 + ARGBToRAWRow = ARGBToRAWRow_SSSE3; 1.800 + } 1.801 + } 1.802 +#elif defined(HAS_ARGBTORAWROW_NEON) 1.803 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.804 + ARGBToRAWRow = ARGBToRAWRow_Any_NEON; 1.805 + if (IS_ALIGNED(width, 8)) { 1.806 + ARGBToRAWRow = ARGBToRAWRow_NEON; 1.807 + } 1.808 + } 1.809 +#endif 1.810 + 1.811 + for (int y = 0; y < height; ++y) { 1.812 + ARGBToRAWRow(src_argb, dst_raw, width); 1.813 + src_argb += src_stride_argb; 1.814 + dst_raw += dst_stride_raw; 1.815 + } 1.816 + return 0; 1.817 +} 1.818 + 1.819 +// Convert ARGB To RGB565. 1.820 +LIBYUV_API 1.821 +int ARGBToRGB565(const uint8* src_argb, int src_stride_argb, 1.822 + uint8* dst_rgb565, int dst_stride_rgb565, 1.823 + int width, int height) { 1.824 + if (!src_argb || !dst_rgb565 || width <= 0 || height == 0) { 1.825 + return -1; 1.826 + } 1.827 + if (height < 0) { 1.828 + height = -height; 1.829 + src_argb = src_argb + (height - 1) * src_stride_argb; 1.830 + src_stride_argb = -src_stride_argb; 1.831 + } 1.832 + // Coalesce rows. 1.833 + if (src_stride_argb == width * 4 && 1.834 + dst_stride_rgb565 == width * 2) { 1.835 + width *= height; 1.836 + height = 1; 1.837 + src_stride_argb = dst_stride_rgb565 = 0; 1.838 + } 1.839 + void (*ARGBToRGB565Row)(const uint8* src_argb, uint8* dst_rgb, int pix) = 1.840 + ARGBToRGB565Row_C; 1.841 +#if defined(HAS_ARGBTORGB565ROW_SSE2) 1.842 + if (TestCpuFlag(kCpuHasSSE2) && width >= 4 && 1.843 + IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { 1.844 + ARGBToRGB565Row = ARGBToRGB565Row_Any_SSE2; 1.845 + if (IS_ALIGNED(width, 4)) { 1.846 + ARGBToRGB565Row = ARGBToRGB565Row_SSE2; 1.847 + } 1.848 + } 1.849 +#elif defined(HAS_ARGBTORGB565ROW_NEON) 1.850 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.851 + ARGBToRGB565Row = ARGBToRGB565Row_Any_NEON; 1.852 + if (IS_ALIGNED(width, 8)) { 1.853 + ARGBToRGB565Row = ARGBToRGB565Row_NEON; 1.854 + } 1.855 + } 1.856 +#endif 1.857 + 1.858 + for (int y = 0; y < height; ++y) { 1.859 + ARGBToRGB565Row(src_argb, dst_rgb565, width); 1.860 + src_argb += src_stride_argb; 1.861 + dst_rgb565 += dst_stride_rgb565; 1.862 + } 1.863 + return 0; 1.864 +} 1.865 + 1.866 +// Convert ARGB To ARGB1555. 1.867 +LIBYUV_API 1.868 +int ARGBToARGB1555(const uint8* src_argb, int src_stride_argb, 1.869 + uint8* dst_argb1555, int dst_stride_argb1555, 1.870 + int width, int height) { 1.871 + if (!src_argb || !dst_argb1555 || width <= 0 || height == 0) { 1.872 + return -1; 1.873 + } 1.874 + if (height < 0) { 1.875 + height = -height; 1.876 + src_argb = src_argb + (height - 1) * src_stride_argb; 1.877 + src_stride_argb = -src_stride_argb; 1.878 + } 1.879 + // Coalesce rows. 1.880 + if (src_stride_argb == width * 4 && 1.881 + dst_stride_argb1555 == width * 2) { 1.882 + width *= height; 1.883 + height = 1; 1.884 + src_stride_argb = dst_stride_argb1555 = 0; 1.885 + } 1.886 + void (*ARGBToARGB1555Row)(const uint8* src_argb, uint8* dst_rgb, int pix) = 1.887 + ARGBToARGB1555Row_C; 1.888 +#if defined(HAS_ARGBTOARGB1555ROW_SSE2) 1.889 + if (TestCpuFlag(kCpuHasSSE2) && width >= 4 && 1.890 + IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { 1.891 + ARGBToARGB1555Row = ARGBToARGB1555Row_Any_SSE2; 1.892 + if (IS_ALIGNED(width, 4)) { 1.893 + ARGBToARGB1555Row = ARGBToARGB1555Row_SSE2; 1.894 + } 1.895 + } 1.896 +#elif defined(HAS_ARGBTOARGB1555ROW_NEON) 1.897 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.898 + ARGBToARGB1555Row = ARGBToARGB1555Row_Any_NEON; 1.899 + if (IS_ALIGNED(width, 8)) { 1.900 + ARGBToARGB1555Row = ARGBToARGB1555Row_NEON; 1.901 + } 1.902 + } 1.903 +#endif 1.904 + 1.905 + for (int y = 0; y < height; ++y) { 1.906 + ARGBToARGB1555Row(src_argb, dst_argb1555, width); 1.907 + src_argb += src_stride_argb; 1.908 + dst_argb1555 += dst_stride_argb1555; 1.909 + } 1.910 + return 0; 1.911 +} 1.912 + 1.913 +// Convert ARGB To ARGB4444. 1.914 +LIBYUV_API 1.915 +int ARGBToARGB4444(const uint8* src_argb, int src_stride_argb, 1.916 + uint8* dst_argb4444, int dst_stride_argb4444, 1.917 + int width, int height) { 1.918 + if (!src_argb || !dst_argb4444 || width <= 0 || height == 0) { 1.919 + return -1; 1.920 + } 1.921 + if (height < 0) { 1.922 + height = -height; 1.923 + src_argb = src_argb + (height - 1) * src_stride_argb; 1.924 + src_stride_argb = -src_stride_argb; 1.925 + } 1.926 + // Coalesce rows. 1.927 + if (src_stride_argb == width * 4 && 1.928 + dst_stride_argb4444 == width * 2) { 1.929 + width *= height; 1.930 + height = 1; 1.931 + src_stride_argb = dst_stride_argb4444 = 0; 1.932 + } 1.933 + void (*ARGBToARGB4444Row)(const uint8* src_argb, uint8* dst_rgb, int pix) = 1.934 + ARGBToARGB4444Row_C; 1.935 +#if defined(HAS_ARGBTOARGB4444ROW_SSE2) 1.936 + if (TestCpuFlag(kCpuHasSSE2) && width >= 4 && 1.937 + IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { 1.938 + ARGBToARGB4444Row = ARGBToARGB4444Row_Any_SSE2; 1.939 + if (IS_ALIGNED(width, 4)) { 1.940 + ARGBToARGB4444Row = ARGBToARGB4444Row_SSE2; 1.941 + } 1.942 + } 1.943 +#elif defined(HAS_ARGBTOARGB4444ROW_NEON) 1.944 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.945 + ARGBToARGB4444Row = ARGBToARGB4444Row_Any_NEON; 1.946 + if (IS_ALIGNED(width, 8)) { 1.947 + ARGBToARGB4444Row = ARGBToARGB4444Row_NEON; 1.948 + } 1.949 + } 1.950 +#endif 1.951 + 1.952 + for (int y = 0; y < height; ++y) { 1.953 + ARGBToARGB4444Row(src_argb, dst_argb4444, width); 1.954 + src_argb += src_stride_argb; 1.955 + dst_argb4444 += dst_stride_argb4444; 1.956 + } 1.957 + return 0; 1.958 +} 1.959 + 1.960 +// Convert ARGB to J420. (JPeg full range I420). 1.961 +LIBYUV_API 1.962 +int ARGBToJ420(const uint8* src_argb, int src_stride_argb, 1.963 + uint8* dst_yj, int dst_stride_yj, 1.964 + uint8* dst_u, int dst_stride_u, 1.965 + uint8* dst_v, int dst_stride_v, 1.966 + int width, int height) { 1.967 + if (!src_argb || 1.968 + !dst_yj || !dst_u || !dst_v || 1.969 + width <= 0 || height == 0) { 1.970 + return -1; 1.971 + } 1.972 + // Negative height means invert the image. 1.973 + if (height < 0) { 1.974 + height = -height; 1.975 + src_argb = src_argb + (height - 1) * src_stride_argb; 1.976 + src_stride_argb = -src_stride_argb; 1.977 + } 1.978 + void (*ARGBToUVJRow)(const uint8* src_argb0, int src_stride_argb, 1.979 + uint8* dst_u, uint8* dst_v, int width) = ARGBToUVJRow_C; 1.980 + void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_yj, int pix) = 1.981 + ARGBToYJRow_C; 1.982 +#if defined(HAS_ARGBTOYJROW_SSSE3) && defined(HAS_ARGBTOUVJROW_SSSE3) 1.983 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { 1.984 + ARGBToUVJRow = ARGBToUVJRow_Any_SSSE3; 1.985 + ARGBToYJRow = ARGBToYJRow_Any_SSSE3; 1.986 + if (IS_ALIGNED(width, 16)) { 1.987 + ARGBToUVJRow = ARGBToUVJRow_Unaligned_SSSE3; 1.988 + ARGBToYJRow = ARGBToYJRow_Unaligned_SSSE3; 1.989 + if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { 1.990 + ARGBToUVJRow = ARGBToUVJRow_SSSE3; 1.991 + if (IS_ALIGNED(dst_yj, 16) && IS_ALIGNED(dst_stride_yj, 16)) { 1.992 + ARGBToYJRow = ARGBToYJRow_SSSE3; 1.993 + } 1.994 + } 1.995 + } 1.996 + } 1.997 +#endif 1.998 +#if defined(HAS_ARGBTOYJROW_AVX2) && defined(HAS_ARGBTOUVJROW_AVX2) 1.999 + if (TestCpuFlag(kCpuHasAVX2) && width >= 32) { 1.1000 + ARGBToYJRow = ARGBToYJRow_Any_AVX2; 1.1001 + if (IS_ALIGNED(width, 32)) { 1.1002 + ARGBToYJRow = ARGBToYJRow_AVX2; 1.1003 + } 1.1004 + } 1.1005 +#endif 1.1006 +#if defined(HAS_ARGBTOYJROW_NEON) 1.1007 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.1008 + ARGBToYJRow = ARGBToYJRow_Any_NEON; 1.1009 + if (IS_ALIGNED(width, 8)) { 1.1010 + ARGBToYJRow = ARGBToYJRow_NEON; 1.1011 + } 1.1012 + if (width >= 16) { 1.1013 + ARGBToUVJRow = ARGBToUVJRow_Any_NEON; 1.1014 + if (IS_ALIGNED(width, 16)) { 1.1015 + ARGBToUVJRow = ARGBToUVJRow_NEON; 1.1016 + } 1.1017 + } 1.1018 + } 1.1019 +#endif 1.1020 + 1.1021 + for (int y = 0; y < height - 1; y += 2) { 1.1022 + ARGBToUVJRow(src_argb, src_stride_argb, dst_u, dst_v, width); 1.1023 + ARGBToYJRow(src_argb, dst_yj, width); 1.1024 + ARGBToYJRow(src_argb + src_stride_argb, dst_yj + dst_stride_yj, width); 1.1025 + src_argb += src_stride_argb * 2; 1.1026 + dst_yj += dst_stride_yj * 2; 1.1027 + dst_u += dst_stride_u; 1.1028 + dst_v += dst_stride_v; 1.1029 + } 1.1030 + if (height & 1) { 1.1031 + ARGBToUVJRow(src_argb, 0, dst_u, dst_v, width); 1.1032 + ARGBToYJRow(src_argb, dst_yj, width); 1.1033 + } 1.1034 + return 0; 1.1035 +} 1.1036 + 1.1037 +// Convert ARGB to J400. 1.1038 +LIBYUV_API 1.1039 +int ARGBToJ400(const uint8* src_argb, int src_stride_argb, 1.1040 + uint8* dst_yj, int dst_stride_yj, 1.1041 + int width, int height) { 1.1042 + if (!src_argb || !dst_yj || width <= 0 || height == 0) { 1.1043 + return -1; 1.1044 + } 1.1045 + if (height < 0) { 1.1046 + height = -height; 1.1047 + src_argb = src_argb + (height - 1) * src_stride_argb; 1.1048 + src_stride_argb = -src_stride_argb; 1.1049 + } 1.1050 + // Coalesce rows. 1.1051 + if (src_stride_argb == width * 4 && 1.1052 + dst_stride_yj == width) { 1.1053 + width *= height; 1.1054 + height = 1; 1.1055 + src_stride_argb = dst_stride_yj = 0; 1.1056 + } 1.1057 + void (*ARGBToYJRow)(const uint8* src_argb, uint8* dst_yj, int pix) = 1.1058 + ARGBToYJRow_C; 1.1059 +#if defined(HAS_ARGBTOYJROW_SSSE3) 1.1060 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 16) { 1.1061 + ARGBToYJRow = ARGBToYJRow_Any_SSSE3; 1.1062 + if (IS_ALIGNED(width, 16)) { 1.1063 + ARGBToYJRow = ARGBToYJRow_Unaligned_SSSE3; 1.1064 + if (IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) && 1.1065 + IS_ALIGNED(dst_yj, 16) && IS_ALIGNED(dst_stride_yj, 16)) { 1.1066 + ARGBToYJRow = ARGBToYJRow_SSSE3; 1.1067 + } 1.1068 + } 1.1069 + } 1.1070 +#endif 1.1071 +#if defined(HAS_ARGBTOYJROW_AVX2) 1.1072 + if (TestCpuFlag(kCpuHasAVX2) && width >= 32) { 1.1073 + ARGBToYJRow = ARGBToYJRow_Any_AVX2; 1.1074 + if (IS_ALIGNED(width, 32)) { 1.1075 + ARGBToYJRow = ARGBToYJRow_AVX2; 1.1076 + } 1.1077 + } 1.1078 +#endif 1.1079 +#if defined(HAS_ARGBTOYJROW_NEON) 1.1080 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.1081 + ARGBToYJRow = ARGBToYJRow_Any_NEON; 1.1082 + if (IS_ALIGNED(width, 8)) { 1.1083 + ARGBToYJRow = ARGBToYJRow_NEON; 1.1084 + } 1.1085 + } 1.1086 +#endif 1.1087 + 1.1088 + for (int y = 0; y < height; ++y) { 1.1089 + ARGBToYJRow(src_argb, dst_yj, width); 1.1090 + src_argb += src_stride_argb; 1.1091 + dst_yj += dst_stride_yj; 1.1092 + } 1.1093 + return 0; 1.1094 +} 1.1095 + 1.1096 +#ifdef __cplusplus 1.1097 +} // extern "C" 1.1098 +} // namespace libyuv 1.1099 +#endif