1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libyuv/source/convert_from.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1196 @@ 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.h" 1.15 + 1.16 +#include "libyuv/basic_types.h" 1.17 +#include "libyuv/convert.h" // For I420Copy 1.18 +#include "libyuv/cpu_id.h" 1.19 +#include "libyuv/format_conversion.h" 1.20 +#include "libyuv/planar_functions.h" 1.21 +#include "libyuv/rotate.h" 1.22 +#include "libyuv/scale.h" // For ScalePlane() 1.23 +#include "libyuv/video_common.h" 1.24 +#include "libyuv/row.h" 1.25 + 1.26 +#ifdef __cplusplus 1.27 +namespace libyuv { 1.28 +extern "C" { 1.29 +#endif 1.30 + 1.31 +#define SUBSAMPLE(v, a, s) (v < 0) ? (-((-v + a) >> s)) : ((v + a) >> s) 1.32 +static __inline int Abs(int v) { 1.33 + return v >= 0 ? v : -v; 1.34 +} 1.35 + 1.36 +// I420 To any I4xx YUV format with mirroring. 1.37 +static int I420ToI4xx(const uint8* src_y, int src_stride_y, 1.38 + const uint8* src_u, int src_stride_u, 1.39 + const uint8* src_v, int src_stride_v, 1.40 + uint8* dst_y, int dst_stride_y, 1.41 + uint8* dst_u, int dst_stride_u, 1.42 + uint8* dst_v, int dst_stride_v, 1.43 + int src_y_width, int src_y_height, 1.44 + int dst_uv_width, int dst_uv_height) { 1.45 + if (src_y_width == 0 || src_y_height == 0 || 1.46 + dst_uv_width <= 0 || dst_uv_height <= 0) { 1.47 + return -1; 1.48 + } 1.49 + const int dst_y_width = Abs(src_y_width); 1.50 + const int dst_y_height = Abs(src_y_height); 1.51 + const int src_uv_width = SUBSAMPLE(src_y_width, 1, 1); 1.52 + const int src_uv_height = SUBSAMPLE(src_y_height, 1, 1); 1.53 + ScalePlane(src_y, src_stride_y, src_y_width, src_y_height, 1.54 + dst_y, dst_stride_y, dst_y_width, dst_y_height, 1.55 + kFilterBilinear); 1.56 + ScalePlane(src_u, src_stride_u, src_uv_width, src_uv_height, 1.57 + dst_u, dst_stride_u, dst_uv_width, dst_uv_height, 1.58 + kFilterBilinear); 1.59 + ScalePlane(src_v, src_stride_v, src_uv_width, src_uv_height, 1.60 + dst_v, dst_stride_v, dst_uv_width, dst_uv_height, 1.61 + kFilterBilinear); 1.62 + return 0; 1.63 +} 1.64 + 1.65 +// 420 chroma is 1/2 width, 1/2 height 1.66 +// 422 chroma is 1/2 width, 1x height 1.67 +LIBYUV_API 1.68 +int I420ToI422(const uint8* src_y, int src_stride_y, 1.69 + const uint8* src_u, int src_stride_u, 1.70 + const uint8* src_v, int src_stride_v, 1.71 + uint8* dst_y, int dst_stride_y, 1.72 + uint8* dst_u, int dst_stride_u, 1.73 + uint8* dst_v, int dst_stride_v, 1.74 + int width, int height) { 1.75 + const int dst_uv_width = (Abs(width) + 1) >> 1; 1.76 + const int dst_uv_height = Abs(height); 1.77 + return I420ToI4xx(src_y, src_stride_y, 1.78 + src_u, src_stride_u, 1.79 + src_v, src_stride_v, 1.80 + dst_y, dst_stride_y, 1.81 + dst_u, dst_stride_u, 1.82 + dst_v, dst_stride_v, 1.83 + width, height, 1.84 + dst_uv_width, dst_uv_height); 1.85 +} 1.86 + 1.87 +// 420 chroma is 1/2 width, 1/2 height 1.88 +// 444 chroma is 1x width, 1x height 1.89 +LIBYUV_API 1.90 +int I420ToI444(const uint8* src_y, int src_stride_y, 1.91 + const uint8* src_u, int src_stride_u, 1.92 + const uint8* src_v, int src_stride_v, 1.93 + uint8* dst_y, int dst_stride_y, 1.94 + uint8* dst_u, int dst_stride_u, 1.95 + uint8* dst_v, int dst_stride_v, 1.96 + int width, int height) { 1.97 + const int dst_uv_width = Abs(width); 1.98 + const int dst_uv_height = Abs(height); 1.99 + return I420ToI4xx(src_y, src_stride_y, 1.100 + src_u, src_stride_u, 1.101 + src_v, src_stride_v, 1.102 + dst_y, dst_stride_y, 1.103 + dst_u, dst_stride_u, 1.104 + dst_v, dst_stride_v, 1.105 + width, height, 1.106 + dst_uv_width, dst_uv_height); 1.107 +} 1.108 + 1.109 +// 420 chroma is 1/2 width, 1/2 height 1.110 +// 411 chroma is 1/4 width, 1x height 1.111 +LIBYUV_API 1.112 +int I420ToI411(const uint8* src_y, int src_stride_y, 1.113 + const uint8* src_u, int src_stride_u, 1.114 + const uint8* src_v, int src_stride_v, 1.115 + uint8* dst_y, int dst_stride_y, 1.116 + uint8* dst_u, int dst_stride_u, 1.117 + uint8* dst_v, int dst_stride_v, 1.118 + int width, int height) { 1.119 + const int dst_uv_width = (Abs(width) + 3) >> 2; 1.120 + const int dst_uv_height = Abs(height); 1.121 + return I420ToI4xx(src_y, src_stride_y, 1.122 + src_u, src_stride_u, 1.123 + src_v, src_stride_v, 1.124 + dst_y, dst_stride_y, 1.125 + dst_u, dst_stride_u, 1.126 + dst_v, dst_stride_v, 1.127 + width, height, 1.128 + dst_uv_width, dst_uv_height); 1.129 +} 1.130 + 1.131 +// Copy to I400. Source can be I420,422,444,400,NV12,NV21 1.132 +LIBYUV_API 1.133 +int I400Copy(const uint8* src_y, int src_stride_y, 1.134 + uint8* dst_y, int dst_stride_y, 1.135 + int width, int height) { 1.136 + if (!src_y || !dst_y || 1.137 + width <= 0 || height == 0) { 1.138 + return -1; 1.139 + } 1.140 + // Negative height means invert the image. 1.141 + if (height < 0) { 1.142 + height = -height; 1.143 + src_y = src_y + (height - 1) * src_stride_y; 1.144 + src_stride_y = -src_stride_y; 1.145 + } 1.146 + CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); 1.147 + return 0; 1.148 +} 1.149 + 1.150 +LIBYUV_API 1.151 +int I422ToYUY2(const uint8* src_y, int src_stride_y, 1.152 + const uint8* src_u, int src_stride_u, 1.153 + const uint8* src_v, int src_stride_v, 1.154 + uint8* dst_yuy2, int dst_stride_yuy2, 1.155 + int width, int height) { 1.156 + if (!src_y || !src_u || !src_v || !dst_yuy2 || 1.157 + width <= 0 || height == 0) { 1.158 + return -1; 1.159 + } 1.160 + // Negative height means invert the image. 1.161 + if (height < 0) { 1.162 + height = -height; 1.163 + dst_yuy2 = dst_yuy2 + (height - 1) * dst_stride_yuy2; 1.164 + dst_stride_yuy2 = -dst_stride_yuy2; 1.165 + } 1.166 + // Coalesce rows. 1.167 + if (src_stride_y == width && 1.168 + src_stride_u * 2 == width && 1.169 + src_stride_v * 2 == width && 1.170 + dst_stride_yuy2 == width * 2) { 1.171 + width *= height; 1.172 + height = 1; 1.173 + src_stride_y = src_stride_u = src_stride_v = dst_stride_yuy2 = 0; 1.174 + } 1.175 + void (*I422ToYUY2Row)(const uint8* src_y, const uint8* src_u, 1.176 + const uint8* src_v, uint8* dst_yuy2, int width) = 1.177 + I422ToYUY2Row_C; 1.178 +#if defined(HAS_I422TOYUY2ROW_SSE2) 1.179 + if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { 1.180 + I422ToYUY2Row = I422ToYUY2Row_Any_SSE2; 1.181 + if (IS_ALIGNED(width, 16)) { 1.182 + I422ToYUY2Row = I422ToYUY2Row_SSE2; 1.183 + } 1.184 + } 1.185 +#elif defined(HAS_I422TOYUY2ROW_NEON) 1.186 + if (TestCpuFlag(kCpuHasNEON) && width >= 16) { 1.187 + I422ToYUY2Row = I422ToYUY2Row_Any_NEON; 1.188 + if (IS_ALIGNED(width, 16)) { 1.189 + I422ToYUY2Row = I422ToYUY2Row_NEON; 1.190 + } 1.191 + } 1.192 +#endif 1.193 + 1.194 + for (int y = 0; y < height; ++y) { 1.195 + I422ToYUY2Row(src_y, src_u, src_v, dst_yuy2, width); 1.196 + src_y += src_stride_y; 1.197 + src_u += src_stride_u; 1.198 + src_v += src_stride_v; 1.199 + dst_yuy2 += dst_stride_yuy2; 1.200 + } 1.201 + return 0; 1.202 +} 1.203 + 1.204 +LIBYUV_API 1.205 +int I420ToYUY2(const uint8* src_y, int src_stride_y, 1.206 + const uint8* src_u, int src_stride_u, 1.207 + const uint8* src_v, int src_stride_v, 1.208 + uint8* dst_yuy2, int dst_stride_yuy2, 1.209 + int width, int height) { 1.210 + if (!src_y || !src_u || !src_v || !dst_yuy2 || 1.211 + width <= 0 || height == 0) { 1.212 + return -1; 1.213 + } 1.214 + // Negative height means invert the image. 1.215 + if (height < 0) { 1.216 + height = -height; 1.217 + dst_yuy2 = dst_yuy2 + (height - 1) * dst_stride_yuy2; 1.218 + dst_stride_yuy2 = -dst_stride_yuy2; 1.219 + } 1.220 + void (*I422ToYUY2Row)(const uint8* src_y, const uint8* src_u, 1.221 + const uint8* src_v, uint8* dst_yuy2, int width) = 1.222 + I422ToYUY2Row_C; 1.223 +#if defined(HAS_I422TOYUY2ROW_SSE2) 1.224 + if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { 1.225 + I422ToYUY2Row = I422ToYUY2Row_Any_SSE2; 1.226 + if (IS_ALIGNED(width, 16)) { 1.227 + I422ToYUY2Row = I422ToYUY2Row_SSE2; 1.228 + } 1.229 + } 1.230 +#elif defined(HAS_I422TOYUY2ROW_NEON) 1.231 + if (TestCpuFlag(kCpuHasNEON) && width >= 16) { 1.232 + I422ToYUY2Row = I422ToYUY2Row_Any_NEON; 1.233 + if (IS_ALIGNED(width, 16)) { 1.234 + I422ToYUY2Row = I422ToYUY2Row_NEON; 1.235 + } 1.236 + } 1.237 +#endif 1.238 + 1.239 + for (int y = 0; y < height - 1; y += 2) { 1.240 + I422ToYUY2Row(src_y, src_u, src_v, dst_yuy2, width); 1.241 + I422ToYUY2Row(src_y + src_stride_y, src_u, src_v, 1.242 + dst_yuy2 + dst_stride_yuy2, width); 1.243 + src_y += src_stride_y * 2; 1.244 + src_u += src_stride_u; 1.245 + src_v += src_stride_v; 1.246 + dst_yuy2 += dst_stride_yuy2 * 2; 1.247 + } 1.248 + if (height & 1) { 1.249 + I422ToYUY2Row(src_y, src_u, src_v, dst_yuy2, width); 1.250 + } 1.251 + return 0; 1.252 +} 1.253 + 1.254 +LIBYUV_API 1.255 +int I422ToUYVY(const uint8* src_y, int src_stride_y, 1.256 + const uint8* src_u, int src_stride_u, 1.257 + const uint8* src_v, int src_stride_v, 1.258 + uint8* dst_uyvy, int dst_stride_uyvy, 1.259 + int width, int height) { 1.260 + if (!src_y || !src_u || !src_v || !dst_uyvy || 1.261 + width <= 0 || height == 0) { 1.262 + return -1; 1.263 + } 1.264 + // Negative height means invert the image. 1.265 + if (height < 0) { 1.266 + height = -height; 1.267 + dst_uyvy = dst_uyvy + (height - 1) * dst_stride_uyvy; 1.268 + dst_stride_uyvy = -dst_stride_uyvy; 1.269 + } 1.270 + // Coalesce rows. 1.271 + if (src_stride_y == width && 1.272 + src_stride_u * 2 == width && 1.273 + src_stride_v * 2 == width && 1.274 + dst_stride_uyvy == width * 2) { 1.275 + width *= height; 1.276 + height = 1; 1.277 + src_stride_y = src_stride_u = src_stride_v = dst_stride_uyvy = 0; 1.278 + } 1.279 + void (*I422ToUYVYRow)(const uint8* src_y, const uint8* src_u, 1.280 + const uint8* src_v, uint8* dst_uyvy, int width) = 1.281 + I422ToUYVYRow_C; 1.282 +#if defined(HAS_I422TOUYVYROW_SSE2) 1.283 + if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { 1.284 + I422ToUYVYRow = I422ToUYVYRow_Any_SSE2; 1.285 + if (IS_ALIGNED(width, 16)) { 1.286 + I422ToUYVYRow = I422ToUYVYRow_SSE2; 1.287 + } 1.288 + } 1.289 +#elif defined(HAS_I422TOUYVYROW_NEON) 1.290 + if (TestCpuFlag(kCpuHasNEON) && width >= 16) { 1.291 + I422ToUYVYRow = I422ToUYVYRow_Any_NEON; 1.292 + if (IS_ALIGNED(width, 16)) { 1.293 + I422ToUYVYRow = I422ToUYVYRow_NEON; 1.294 + } 1.295 + } 1.296 +#endif 1.297 + 1.298 + for (int y = 0; y < height; ++y) { 1.299 + I422ToUYVYRow(src_y, src_u, src_v, dst_uyvy, width); 1.300 + src_y += src_stride_y; 1.301 + src_u += src_stride_u; 1.302 + src_v += src_stride_v; 1.303 + dst_uyvy += dst_stride_uyvy; 1.304 + } 1.305 + return 0; 1.306 +} 1.307 + 1.308 +LIBYUV_API 1.309 +int I420ToUYVY(const uint8* src_y, int src_stride_y, 1.310 + const uint8* src_u, int src_stride_u, 1.311 + const uint8* src_v, int src_stride_v, 1.312 + uint8* dst_uyvy, int dst_stride_uyvy, 1.313 + int width, int height) { 1.314 + if (!src_y || !src_u || !src_v || !dst_uyvy || 1.315 + width <= 0 || height == 0) { 1.316 + return -1; 1.317 + } 1.318 + // Negative height means invert the image. 1.319 + if (height < 0) { 1.320 + height = -height; 1.321 + dst_uyvy = dst_uyvy + (height - 1) * dst_stride_uyvy; 1.322 + dst_stride_uyvy = -dst_stride_uyvy; 1.323 + } 1.324 + void (*I422ToUYVYRow)(const uint8* src_y, const uint8* src_u, 1.325 + const uint8* src_v, uint8* dst_uyvy, int width) = 1.326 + I422ToUYVYRow_C; 1.327 +#if defined(HAS_I422TOUYVYROW_SSE2) 1.328 + if (TestCpuFlag(kCpuHasSSE2) && width >= 16) { 1.329 + I422ToUYVYRow = I422ToUYVYRow_Any_SSE2; 1.330 + if (IS_ALIGNED(width, 16)) { 1.331 + I422ToUYVYRow = I422ToUYVYRow_SSE2; 1.332 + } 1.333 + } 1.334 +#elif defined(HAS_I422TOUYVYROW_NEON) 1.335 + if (TestCpuFlag(kCpuHasNEON) && width >= 16) { 1.336 + I422ToUYVYRow = I422ToUYVYRow_Any_NEON; 1.337 + if (IS_ALIGNED(width, 16)) { 1.338 + I422ToUYVYRow = I422ToUYVYRow_NEON; 1.339 + } 1.340 + } 1.341 +#endif 1.342 + 1.343 + for (int y = 0; y < height - 1; y += 2) { 1.344 + I422ToUYVYRow(src_y, src_u, src_v, dst_uyvy, width); 1.345 + I422ToUYVYRow(src_y + src_stride_y, src_u, src_v, 1.346 + dst_uyvy + dst_stride_uyvy, width); 1.347 + src_y += src_stride_y * 2; 1.348 + src_u += src_stride_u; 1.349 + src_v += src_stride_v; 1.350 + dst_uyvy += dst_stride_uyvy * 2; 1.351 + } 1.352 + if (height & 1) { 1.353 + I422ToUYVYRow(src_y, src_u, src_v, dst_uyvy, width); 1.354 + } 1.355 + return 0; 1.356 +} 1.357 + 1.358 +LIBYUV_API 1.359 +int I420ToNV12(const uint8* src_y, int src_stride_y, 1.360 + const uint8* src_u, int src_stride_u, 1.361 + const uint8* src_v, int src_stride_v, 1.362 + uint8* dst_y, int dst_stride_y, 1.363 + uint8* dst_uv, int dst_stride_uv, 1.364 + int width, int height) { 1.365 + if (!src_y || !src_u || !src_v || !dst_y || !dst_uv || 1.366 + width <= 0 || height == 0) { 1.367 + return -1; 1.368 + } 1.369 + // Negative height means invert the image. 1.370 + if (height < 0) { 1.371 + height = -height; 1.372 + int halfheight = (height + 1) >> 1; 1.373 + dst_y = dst_y + (height - 1) * dst_stride_y; 1.374 + dst_uv = dst_uv + (halfheight - 1) * dst_stride_uv; 1.375 + dst_stride_y = -dst_stride_y; 1.376 + dst_stride_uv = -dst_stride_uv; 1.377 + } 1.378 + // Coalesce rows. 1.379 + int halfwidth = (width + 1) >> 1; 1.380 + int halfheight = (height + 1) >> 1; 1.381 + if (src_stride_y == width && 1.382 + dst_stride_y == width) { 1.383 + width *= height; 1.384 + height = 1; 1.385 + src_stride_y = dst_stride_y = 0; 1.386 + } 1.387 + // Coalesce rows. 1.388 + if (src_stride_u == halfwidth && 1.389 + src_stride_v == halfwidth && 1.390 + dst_stride_uv == halfwidth * 2) { 1.391 + halfwidth *= halfheight; 1.392 + halfheight = 1; 1.393 + src_stride_u = src_stride_v = dst_stride_uv = 0; 1.394 + } 1.395 + void (*MergeUVRow_)(const uint8* src_u, const uint8* src_v, uint8* dst_uv, 1.396 + int width) = MergeUVRow_C; 1.397 +#if defined(HAS_MERGEUVROW_SSE2) 1.398 + if (TestCpuFlag(kCpuHasSSE2) && halfwidth >= 16) { 1.399 + MergeUVRow_ = MergeUVRow_Any_SSE2; 1.400 + if (IS_ALIGNED(halfwidth, 16)) { 1.401 + MergeUVRow_ = MergeUVRow_Unaligned_SSE2; 1.402 + if (IS_ALIGNED(src_u, 16) && IS_ALIGNED(src_stride_u, 16) && 1.403 + IS_ALIGNED(src_v, 16) && IS_ALIGNED(src_stride_v, 16) && 1.404 + IS_ALIGNED(dst_uv, 16) && IS_ALIGNED(dst_stride_uv, 16)) { 1.405 + MergeUVRow_ = MergeUVRow_SSE2; 1.406 + } 1.407 + } 1.408 + } 1.409 +#endif 1.410 +#if defined(HAS_MERGEUVROW_AVX2) 1.411 + if (TestCpuFlag(kCpuHasAVX2) && halfwidth >= 32) { 1.412 + MergeUVRow_ = MergeUVRow_Any_AVX2; 1.413 + if (IS_ALIGNED(halfwidth, 32)) { 1.414 + MergeUVRow_ = MergeUVRow_AVX2; 1.415 + } 1.416 + } 1.417 +#endif 1.418 +#if defined(HAS_MERGEUVROW_NEON) 1.419 + if (TestCpuFlag(kCpuHasNEON) && halfwidth >= 16) { 1.420 + MergeUVRow_ = MergeUVRow_Any_NEON; 1.421 + if (IS_ALIGNED(halfwidth, 16)) { 1.422 + MergeUVRow_ = MergeUVRow_NEON; 1.423 + } 1.424 + } 1.425 +#endif 1.426 + 1.427 + CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); 1.428 + for (int y = 0; y < halfheight; ++y) { 1.429 + // Merge a row of U and V into a row of UV. 1.430 + MergeUVRow_(src_u, src_v, dst_uv, halfwidth); 1.431 + src_u += src_stride_u; 1.432 + src_v += src_stride_v; 1.433 + dst_uv += dst_stride_uv; 1.434 + } 1.435 + return 0; 1.436 +} 1.437 + 1.438 +LIBYUV_API 1.439 +int I420ToNV21(const uint8* src_y, int src_stride_y, 1.440 + const uint8* src_u, int src_stride_u, 1.441 + const uint8* src_v, int src_stride_v, 1.442 + uint8* dst_y, int dst_stride_y, 1.443 + uint8* dst_vu, int dst_stride_vu, 1.444 + int width, int height) { 1.445 + return I420ToNV12(src_y, src_stride_y, 1.446 + src_v, src_stride_v, 1.447 + src_u, src_stride_u, 1.448 + dst_y, src_stride_y, 1.449 + dst_vu, dst_stride_vu, 1.450 + width, height); 1.451 +} 1.452 + 1.453 +// Convert I420 to ARGB. 1.454 +LIBYUV_API 1.455 +int I420ToARGB(const uint8* src_y, int src_stride_y, 1.456 + const uint8* src_u, int src_stride_u, 1.457 + const uint8* src_v, int src_stride_v, 1.458 + uint8* dst_argb, int dst_stride_argb, 1.459 + int width, int height) { 1.460 + if (!src_y || !src_u || !src_v || !dst_argb || 1.461 + width <= 0 || height == 0) { 1.462 + return -1; 1.463 + } 1.464 + // Negative height means invert the image. 1.465 + if (height < 0) { 1.466 + height = -height; 1.467 + dst_argb = dst_argb + (height - 1) * dst_stride_argb; 1.468 + dst_stride_argb = -dst_stride_argb; 1.469 + } 1.470 + void (*I422ToARGBRow)(const uint8* y_buf, 1.471 + const uint8* u_buf, 1.472 + const uint8* v_buf, 1.473 + uint8* rgb_buf, 1.474 + int width) = I422ToARGBRow_C; 1.475 +#if defined(HAS_I422TOARGBROW_SSSE3) 1.476 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { 1.477 + I422ToARGBRow = I422ToARGBRow_Any_SSSE3; 1.478 + if (IS_ALIGNED(width, 8)) { 1.479 + I422ToARGBRow = I422ToARGBRow_Unaligned_SSSE3; 1.480 + if (IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) { 1.481 + I422ToARGBRow = I422ToARGBRow_SSSE3; 1.482 + } 1.483 + } 1.484 + } 1.485 +#endif 1.486 +#if defined(HAS_I422TOARGBROW_AVX2) 1.487 + if (TestCpuFlag(kCpuHasAVX2) && width >= 16) { 1.488 + I422ToARGBRow = I422ToARGBRow_Any_AVX2; 1.489 + if (IS_ALIGNED(width, 16)) { 1.490 + I422ToARGBRow = I422ToARGBRow_AVX2; 1.491 + } 1.492 + } 1.493 +#endif 1.494 +#if defined(HAS_I422TOARGBROW_NEON) 1.495 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.496 + I422ToARGBRow = I422ToARGBRow_Any_NEON; 1.497 + if (IS_ALIGNED(width, 8)) { 1.498 + I422ToARGBRow = I422ToARGBRow_NEON; 1.499 + } 1.500 + } 1.501 +#endif 1.502 +#if defined(HAS_I422TOARGBROW_MIPS_DSPR2) 1.503 + if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) && 1.504 + IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) && 1.505 + IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) && 1.506 + IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) && 1.507 + IS_ALIGNED(dst_argb, 4) && IS_ALIGNED(dst_stride_argb, 4)) { 1.508 + I422ToARGBRow = I422ToARGBRow_MIPS_DSPR2; 1.509 + } 1.510 +#endif 1.511 + 1.512 + for (int y = 0; y < height; ++y) { 1.513 + I422ToARGBRow(src_y, src_u, src_v, dst_argb, width); 1.514 + dst_argb += dst_stride_argb; 1.515 + src_y += src_stride_y; 1.516 + if (y & 1) { 1.517 + src_u += src_stride_u; 1.518 + src_v += src_stride_v; 1.519 + } 1.520 + } 1.521 + return 0; 1.522 +} 1.523 + 1.524 +// Convert I420 to BGRA. 1.525 +LIBYUV_API 1.526 +int I420ToBGRA(const uint8* src_y, int src_stride_y, 1.527 + const uint8* src_u, int src_stride_u, 1.528 + const uint8* src_v, int src_stride_v, 1.529 + uint8* dst_bgra, int dst_stride_bgra, 1.530 + int width, int height) { 1.531 + if (!src_y || !src_u || !src_v || !dst_bgra || 1.532 + width <= 0 || height == 0) { 1.533 + return -1; 1.534 + } 1.535 + // Negative height means invert the image. 1.536 + if (height < 0) { 1.537 + height = -height; 1.538 + dst_bgra = dst_bgra + (height - 1) * dst_stride_bgra; 1.539 + dst_stride_bgra = -dst_stride_bgra; 1.540 + } 1.541 + void (*I422ToBGRARow)(const uint8* y_buf, 1.542 + const uint8* u_buf, 1.543 + const uint8* v_buf, 1.544 + uint8* rgb_buf, 1.545 + int width) = I422ToBGRARow_C; 1.546 +#if defined(HAS_I422TOBGRAROW_SSSE3) 1.547 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { 1.548 + I422ToBGRARow = I422ToBGRARow_Any_SSSE3; 1.549 + if (IS_ALIGNED(width, 8)) { 1.550 + I422ToBGRARow = I422ToBGRARow_Unaligned_SSSE3; 1.551 + if (IS_ALIGNED(dst_bgra, 16) && IS_ALIGNED(dst_stride_bgra, 16)) { 1.552 + I422ToBGRARow = I422ToBGRARow_SSSE3; 1.553 + } 1.554 + } 1.555 + } 1.556 +#elif defined(HAS_I422TOBGRAROW_NEON) 1.557 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.558 + I422ToBGRARow = I422ToBGRARow_Any_NEON; 1.559 + if (IS_ALIGNED(width, 8)) { 1.560 + I422ToBGRARow = I422ToBGRARow_NEON; 1.561 + } 1.562 + } 1.563 +#elif defined(HAS_I422TOBGRAROW_MIPS_DSPR2) 1.564 + if (TestCpuFlag(kCpuHasMIPS_DSPR2) && IS_ALIGNED(width, 4) && 1.565 + IS_ALIGNED(src_y, 4) && IS_ALIGNED(src_stride_y, 4) && 1.566 + IS_ALIGNED(src_u, 2) && IS_ALIGNED(src_stride_u, 2) && 1.567 + IS_ALIGNED(src_v, 2) && IS_ALIGNED(src_stride_v, 2) && 1.568 + IS_ALIGNED(dst_bgra, 4) && IS_ALIGNED(dst_stride_bgra, 4)) { 1.569 + I422ToBGRARow = I422ToBGRARow_MIPS_DSPR2; 1.570 + } 1.571 +#endif 1.572 + 1.573 + for (int y = 0; y < height; ++y) { 1.574 + I422ToBGRARow(src_y, src_u, src_v, dst_bgra, width); 1.575 + dst_bgra += dst_stride_bgra; 1.576 + src_y += src_stride_y; 1.577 + if (y & 1) { 1.578 + src_u += src_stride_u; 1.579 + src_v += src_stride_v; 1.580 + } 1.581 + } 1.582 + return 0; 1.583 +} 1.584 + 1.585 +// Convert I420 to ABGR. 1.586 +LIBYUV_API 1.587 +int I420ToABGR(const uint8* src_y, int src_stride_y, 1.588 + const uint8* src_u, int src_stride_u, 1.589 + const uint8* src_v, int src_stride_v, 1.590 + uint8* dst_abgr, int dst_stride_abgr, 1.591 + int width, int height) { 1.592 + if (!src_y || !src_u || !src_v || !dst_abgr || 1.593 + width <= 0 || height == 0) { 1.594 + return -1; 1.595 + } 1.596 + // Negative height means invert the image. 1.597 + if (height < 0) { 1.598 + height = -height; 1.599 + dst_abgr = dst_abgr + (height - 1) * dst_stride_abgr; 1.600 + dst_stride_abgr = -dst_stride_abgr; 1.601 + } 1.602 + void (*I422ToABGRRow)(const uint8* y_buf, 1.603 + const uint8* u_buf, 1.604 + const uint8* v_buf, 1.605 + uint8* rgb_buf, 1.606 + int width) = I422ToABGRRow_C; 1.607 +#if defined(HAS_I422TOABGRROW_SSSE3) 1.608 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { 1.609 + I422ToABGRRow = I422ToABGRRow_Any_SSSE3; 1.610 + if (IS_ALIGNED(width, 8)) { 1.611 + I422ToABGRRow = I422ToABGRRow_Unaligned_SSSE3; 1.612 + if (IS_ALIGNED(dst_abgr, 16) && IS_ALIGNED(dst_stride_abgr, 16)) { 1.613 + I422ToABGRRow = I422ToABGRRow_SSSE3; 1.614 + } 1.615 + } 1.616 + } 1.617 +#elif defined(HAS_I422TOABGRROW_NEON) 1.618 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.619 + I422ToABGRRow = I422ToABGRRow_Any_NEON; 1.620 + if (IS_ALIGNED(width, 8)) { 1.621 + I422ToABGRRow = I422ToABGRRow_NEON; 1.622 + } 1.623 + } 1.624 +#endif 1.625 + 1.626 + for (int y = 0; y < height; ++y) { 1.627 + I422ToABGRRow(src_y, src_u, src_v, dst_abgr, width); 1.628 + dst_abgr += dst_stride_abgr; 1.629 + src_y += src_stride_y; 1.630 + if (y & 1) { 1.631 + src_u += src_stride_u; 1.632 + src_v += src_stride_v; 1.633 + } 1.634 + } 1.635 + return 0; 1.636 +} 1.637 + 1.638 +// Convert I420 to RGBA. 1.639 +LIBYUV_API 1.640 +int I420ToRGBA(const uint8* src_y, int src_stride_y, 1.641 + const uint8* src_u, int src_stride_u, 1.642 + const uint8* src_v, int src_stride_v, 1.643 + uint8* dst_rgba, int dst_stride_rgba, 1.644 + int width, int height) { 1.645 + if (!src_y || !src_u || !src_v || !dst_rgba || 1.646 + width <= 0 || height == 0) { 1.647 + return -1; 1.648 + } 1.649 + // Negative height means invert the image. 1.650 + if (height < 0) { 1.651 + height = -height; 1.652 + dst_rgba = dst_rgba + (height - 1) * dst_stride_rgba; 1.653 + dst_stride_rgba = -dst_stride_rgba; 1.654 + } 1.655 + void (*I422ToRGBARow)(const uint8* y_buf, 1.656 + const uint8* u_buf, 1.657 + const uint8* v_buf, 1.658 + uint8* rgb_buf, 1.659 + int width) = I422ToRGBARow_C; 1.660 +#if defined(HAS_I422TORGBAROW_SSSE3) 1.661 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { 1.662 + I422ToRGBARow = I422ToRGBARow_Any_SSSE3; 1.663 + if (IS_ALIGNED(width, 8)) { 1.664 + I422ToRGBARow = I422ToRGBARow_Unaligned_SSSE3; 1.665 + if (IS_ALIGNED(dst_rgba, 16) && IS_ALIGNED(dst_stride_rgba, 16)) { 1.666 + I422ToRGBARow = I422ToRGBARow_SSSE3; 1.667 + } 1.668 + } 1.669 + } 1.670 +#elif defined(HAS_I422TORGBAROW_NEON) 1.671 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.672 + I422ToRGBARow = I422ToRGBARow_Any_NEON; 1.673 + if (IS_ALIGNED(width, 8)) { 1.674 + I422ToRGBARow = I422ToRGBARow_NEON; 1.675 + } 1.676 + } 1.677 +#endif 1.678 + 1.679 + for (int y = 0; y < height; ++y) { 1.680 + I422ToRGBARow(src_y, src_u, src_v, dst_rgba, width); 1.681 + dst_rgba += dst_stride_rgba; 1.682 + src_y += src_stride_y; 1.683 + if (y & 1) { 1.684 + src_u += src_stride_u; 1.685 + src_v += src_stride_v; 1.686 + } 1.687 + } 1.688 + return 0; 1.689 +} 1.690 + 1.691 +// Convert I420 to RGB24. 1.692 +LIBYUV_API 1.693 +int I420ToRGB24(const uint8* src_y, int src_stride_y, 1.694 + const uint8* src_u, int src_stride_u, 1.695 + const uint8* src_v, int src_stride_v, 1.696 + uint8* dst_rgb24, int dst_stride_rgb24, 1.697 + int width, int height) { 1.698 + if (!src_y || !src_u || !src_v || !dst_rgb24 || 1.699 + width <= 0 || height == 0) { 1.700 + return -1; 1.701 + } 1.702 + // Negative height means invert the image. 1.703 + if (height < 0) { 1.704 + height = -height; 1.705 + dst_rgb24 = dst_rgb24 + (height - 1) * dst_stride_rgb24; 1.706 + dst_stride_rgb24 = -dst_stride_rgb24; 1.707 + } 1.708 + void (*I422ToRGB24Row)(const uint8* y_buf, 1.709 + const uint8* u_buf, 1.710 + const uint8* v_buf, 1.711 + uint8* rgb_buf, 1.712 + int width) = I422ToRGB24Row_C; 1.713 +#if defined(HAS_I422TORGB24ROW_SSSE3) 1.714 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { 1.715 + I422ToRGB24Row = I422ToRGB24Row_Any_SSSE3; 1.716 + if (IS_ALIGNED(width, 8)) { 1.717 + I422ToRGB24Row = I422ToRGB24Row_SSSE3; 1.718 + } 1.719 + } 1.720 +#elif defined(HAS_I422TORGB24ROW_NEON) 1.721 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.722 + I422ToRGB24Row = I422ToRGB24Row_Any_NEON; 1.723 + if (IS_ALIGNED(width, 8)) { 1.724 + I422ToRGB24Row = I422ToRGB24Row_NEON; 1.725 + } 1.726 + } 1.727 +#endif 1.728 + 1.729 + for (int y = 0; y < height; ++y) { 1.730 + I422ToRGB24Row(src_y, src_u, src_v, dst_rgb24, width); 1.731 + dst_rgb24 += dst_stride_rgb24; 1.732 + src_y += src_stride_y; 1.733 + if (y & 1) { 1.734 + src_u += src_stride_u; 1.735 + src_v += src_stride_v; 1.736 + } 1.737 + } 1.738 + return 0; 1.739 +} 1.740 + 1.741 +// Convert I420 to RAW. 1.742 +LIBYUV_API 1.743 +int I420ToRAW(const uint8* src_y, int src_stride_y, 1.744 + const uint8* src_u, int src_stride_u, 1.745 + const uint8* src_v, int src_stride_v, 1.746 + uint8* dst_raw, int dst_stride_raw, 1.747 + int width, int height) { 1.748 + if (!src_y || !src_u || !src_v || !dst_raw || 1.749 + width <= 0 || height == 0) { 1.750 + return -1; 1.751 + } 1.752 + // Negative height means invert the image. 1.753 + if (height < 0) { 1.754 + height = -height; 1.755 + dst_raw = dst_raw + (height - 1) * dst_stride_raw; 1.756 + dst_stride_raw = -dst_stride_raw; 1.757 + } 1.758 + void (*I422ToRAWRow)(const uint8* y_buf, 1.759 + const uint8* u_buf, 1.760 + const uint8* v_buf, 1.761 + uint8* rgb_buf, 1.762 + int width) = I422ToRAWRow_C; 1.763 +#if defined(HAS_I422TORAWROW_SSSE3) 1.764 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { 1.765 + I422ToRAWRow = I422ToRAWRow_Any_SSSE3; 1.766 + if (IS_ALIGNED(width, 8)) { 1.767 + I422ToRAWRow = I422ToRAWRow_SSSE3; 1.768 + } 1.769 + } 1.770 +#elif defined(HAS_I422TORAWROW_NEON) 1.771 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.772 + I422ToRAWRow = I422ToRAWRow_Any_NEON; 1.773 + if (IS_ALIGNED(width, 8)) { 1.774 + I422ToRAWRow = I422ToRAWRow_NEON; 1.775 + } 1.776 + } 1.777 +#endif 1.778 + 1.779 + for (int y = 0; y < height; ++y) { 1.780 + I422ToRAWRow(src_y, src_u, src_v, dst_raw, width); 1.781 + dst_raw += dst_stride_raw; 1.782 + src_y += src_stride_y; 1.783 + if (y & 1) { 1.784 + src_u += src_stride_u; 1.785 + src_v += src_stride_v; 1.786 + } 1.787 + } 1.788 + return 0; 1.789 +} 1.790 + 1.791 +// Convert I420 to ARGB1555. 1.792 +LIBYUV_API 1.793 +int I420ToARGB1555(const uint8* src_y, int src_stride_y, 1.794 + const uint8* src_u, int src_stride_u, 1.795 + const uint8* src_v, int src_stride_v, 1.796 + uint8* dst_argb1555, int dst_stride_argb1555, 1.797 + int width, int height) { 1.798 + if (!src_y || !src_u || !src_v || !dst_argb1555 || 1.799 + width <= 0 || height == 0) { 1.800 + return -1; 1.801 + } 1.802 + // Negative height means invert the image. 1.803 + if (height < 0) { 1.804 + height = -height; 1.805 + dst_argb1555 = dst_argb1555 + (height - 1) * dst_stride_argb1555; 1.806 + dst_stride_argb1555 = -dst_stride_argb1555; 1.807 + } 1.808 + void (*I422ToARGB1555Row)(const uint8* y_buf, 1.809 + const uint8* u_buf, 1.810 + const uint8* v_buf, 1.811 + uint8* rgb_buf, 1.812 + int width) = I422ToARGB1555Row_C; 1.813 +#if defined(HAS_I422TOARGB1555ROW_SSSE3) 1.814 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { 1.815 + I422ToARGB1555Row = I422ToARGB1555Row_Any_SSSE3; 1.816 + if (IS_ALIGNED(width, 8)) { 1.817 + I422ToARGB1555Row = I422ToARGB1555Row_SSSE3; 1.818 + } 1.819 + } 1.820 +#elif defined(HAS_I422TOARGB1555ROW_NEON) 1.821 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.822 + I422ToARGB1555Row = I422ToARGB1555Row_Any_NEON; 1.823 + if (IS_ALIGNED(width, 8)) { 1.824 + I422ToARGB1555Row = I422ToARGB1555Row_NEON; 1.825 + } 1.826 + } 1.827 +#endif 1.828 + 1.829 + for (int y = 0; y < height; ++y) { 1.830 + I422ToARGB1555Row(src_y, src_u, src_v, dst_argb1555, width); 1.831 + dst_argb1555 += dst_stride_argb1555; 1.832 + src_y += src_stride_y; 1.833 + if (y & 1) { 1.834 + src_u += src_stride_u; 1.835 + src_v += src_stride_v; 1.836 + } 1.837 + } 1.838 + return 0; 1.839 +} 1.840 + 1.841 + 1.842 +// Convert I420 to ARGB4444. 1.843 +LIBYUV_API 1.844 +int I420ToARGB4444(const uint8* src_y, int src_stride_y, 1.845 + const uint8* src_u, int src_stride_u, 1.846 + const uint8* src_v, int src_stride_v, 1.847 + uint8* dst_argb4444, int dst_stride_argb4444, 1.848 + int width, int height) { 1.849 + if (!src_y || !src_u || !src_v || !dst_argb4444 || 1.850 + width <= 0 || height == 0) { 1.851 + return -1; 1.852 + } 1.853 + // Negative height means invert the image. 1.854 + if (height < 0) { 1.855 + height = -height; 1.856 + dst_argb4444 = dst_argb4444 + (height - 1) * dst_stride_argb4444; 1.857 + dst_stride_argb4444 = -dst_stride_argb4444; 1.858 + } 1.859 + void (*I422ToARGB4444Row)(const uint8* y_buf, 1.860 + const uint8* u_buf, 1.861 + const uint8* v_buf, 1.862 + uint8* rgb_buf, 1.863 + int width) = I422ToARGB4444Row_C; 1.864 +#if defined(HAS_I422TOARGB4444ROW_SSSE3) 1.865 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { 1.866 + I422ToARGB4444Row = I422ToARGB4444Row_Any_SSSE3; 1.867 + if (IS_ALIGNED(width, 8)) { 1.868 + I422ToARGB4444Row = I422ToARGB4444Row_SSSE3; 1.869 + } 1.870 + } 1.871 +#elif defined(HAS_I422TOARGB4444ROW_NEON) 1.872 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.873 + I422ToARGB4444Row = I422ToARGB4444Row_Any_NEON; 1.874 + if (IS_ALIGNED(width, 8)) { 1.875 + I422ToARGB4444Row = I422ToARGB4444Row_NEON; 1.876 + } 1.877 + } 1.878 +#endif 1.879 + 1.880 + for (int y = 0; y < height; ++y) { 1.881 + I422ToARGB4444Row(src_y, src_u, src_v, dst_argb4444, width); 1.882 + dst_argb4444 += dst_stride_argb4444; 1.883 + src_y += src_stride_y; 1.884 + if (y & 1) { 1.885 + src_u += src_stride_u; 1.886 + src_v += src_stride_v; 1.887 + } 1.888 + } 1.889 + return 0; 1.890 +} 1.891 + 1.892 +// Convert I420 to RGB565. 1.893 +LIBYUV_API 1.894 +int I420ToRGB565(const uint8* src_y, int src_stride_y, 1.895 + const uint8* src_u, int src_stride_u, 1.896 + const uint8* src_v, int src_stride_v, 1.897 + uint8* dst_rgb565, int dst_stride_rgb565, 1.898 + int width, int height) { 1.899 + if (!src_y || !src_u || !src_v || !dst_rgb565 || 1.900 + width <= 0 || height == 0) { 1.901 + return -1; 1.902 + } 1.903 + // Negative height means invert the image. 1.904 + if (height < 0) { 1.905 + height = -height; 1.906 + dst_rgb565 = dst_rgb565 + (height - 1) * dst_stride_rgb565; 1.907 + dst_stride_rgb565 = -dst_stride_rgb565; 1.908 + } 1.909 + void (*I422ToRGB565Row)(const uint8* y_buf, 1.910 + const uint8* u_buf, 1.911 + const uint8* v_buf, 1.912 + uint8* rgb_buf, 1.913 + int width) = I422ToRGB565Row_C; 1.914 +#if defined(HAS_I422TORGB565ROW_SSSE3) 1.915 + if (TestCpuFlag(kCpuHasSSSE3) && width >= 8) { 1.916 + I422ToRGB565Row = I422ToRGB565Row_Any_SSSE3; 1.917 + if (IS_ALIGNED(width, 8)) { 1.918 + I422ToRGB565Row = I422ToRGB565Row_SSSE3; 1.919 + } 1.920 + } 1.921 +#elif defined(HAS_I422TORGB565ROW_NEON) 1.922 + if (TestCpuFlag(kCpuHasNEON) && width >= 8) { 1.923 + I422ToRGB565Row = I422ToRGB565Row_Any_NEON; 1.924 + if (IS_ALIGNED(width, 8)) { 1.925 + I422ToRGB565Row = I422ToRGB565Row_NEON; 1.926 + } 1.927 + } 1.928 +#endif 1.929 + 1.930 + for (int y = 0; y < height; ++y) { 1.931 + I422ToRGB565Row(src_y, src_u, src_v, dst_rgb565, width); 1.932 + dst_rgb565 += dst_stride_rgb565; 1.933 + src_y += src_stride_y; 1.934 + if (y & 1) { 1.935 + src_u += src_stride_u; 1.936 + src_v += src_stride_v; 1.937 + } 1.938 + } 1.939 + return 0; 1.940 +} 1.941 + 1.942 +// Convert I420 to specified format 1.943 +LIBYUV_API 1.944 +int ConvertFromI420(const uint8* y, int y_stride, 1.945 + const uint8* u, int u_stride, 1.946 + const uint8* v, int v_stride, 1.947 + uint8* dst_sample, int dst_sample_stride, 1.948 + int width, int height, 1.949 + uint32 fourcc) { 1.950 + uint32 format = CanonicalFourCC(fourcc); 1.951 + if (!y || !u|| !v || !dst_sample || 1.952 + width <= 0 || height == 0) { 1.953 + return -1; 1.954 + } 1.955 + int r = 0; 1.956 + switch (format) { 1.957 + // Single plane formats 1.958 + case FOURCC_YUY2: 1.959 + r = I420ToYUY2(y, y_stride, 1.960 + u, u_stride, 1.961 + v, v_stride, 1.962 + dst_sample, 1.963 + dst_sample_stride ? dst_sample_stride : width * 2, 1.964 + width, height); 1.965 + break; 1.966 + case FOURCC_UYVY: 1.967 + r = I420ToUYVY(y, y_stride, 1.968 + u, u_stride, 1.969 + v, v_stride, 1.970 + dst_sample, 1.971 + dst_sample_stride ? dst_sample_stride : width * 2, 1.972 + width, height); 1.973 + break; 1.974 + case FOURCC_RGBP: 1.975 + r = I420ToRGB565(y, y_stride, 1.976 + u, u_stride, 1.977 + v, v_stride, 1.978 + dst_sample, 1.979 + dst_sample_stride ? dst_sample_stride : width * 2, 1.980 + width, height); 1.981 + break; 1.982 + case FOURCC_RGBO: 1.983 + r = I420ToARGB1555(y, y_stride, 1.984 + u, u_stride, 1.985 + v, v_stride, 1.986 + dst_sample, 1.987 + dst_sample_stride ? dst_sample_stride : width * 2, 1.988 + width, height); 1.989 + break; 1.990 + case FOURCC_R444: 1.991 + r = I420ToARGB4444(y, y_stride, 1.992 + u, u_stride, 1.993 + v, v_stride, 1.994 + dst_sample, 1.995 + dst_sample_stride ? dst_sample_stride : width * 2, 1.996 + width, height); 1.997 + break; 1.998 + case FOURCC_24BG: 1.999 + r = I420ToRGB24(y, y_stride, 1.1000 + u, u_stride, 1.1001 + v, v_stride, 1.1002 + dst_sample, 1.1003 + dst_sample_stride ? dst_sample_stride : width * 3, 1.1004 + width, height); 1.1005 + break; 1.1006 + case FOURCC_RAW: 1.1007 + r = I420ToRAW(y, y_stride, 1.1008 + u, u_stride, 1.1009 + v, v_stride, 1.1010 + dst_sample, 1.1011 + dst_sample_stride ? dst_sample_stride : width * 3, 1.1012 + width, height); 1.1013 + break; 1.1014 + case FOURCC_ARGB: 1.1015 + r = I420ToARGB(y, y_stride, 1.1016 + u, u_stride, 1.1017 + v, v_stride, 1.1018 + dst_sample, 1.1019 + dst_sample_stride ? dst_sample_stride : width * 4, 1.1020 + width, height); 1.1021 + break; 1.1022 + case FOURCC_BGRA: 1.1023 + r = I420ToBGRA(y, y_stride, 1.1024 + u, u_stride, 1.1025 + v, v_stride, 1.1026 + dst_sample, 1.1027 + dst_sample_stride ? dst_sample_stride : width * 4, 1.1028 + width, height); 1.1029 + break; 1.1030 + case FOURCC_ABGR: 1.1031 + r = I420ToABGR(y, y_stride, 1.1032 + u, u_stride, 1.1033 + v, v_stride, 1.1034 + dst_sample, 1.1035 + dst_sample_stride ? dst_sample_stride : width * 4, 1.1036 + width, height); 1.1037 + break; 1.1038 + case FOURCC_RGBA: 1.1039 + r = I420ToRGBA(y, y_stride, 1.1040 + u, u_stride, 1.1041 + v, v_stride, 1.1042 + dst_sample, 1.1043 + dst_sample_stride ? dst_sample_stride : width * 4, 1.1044 + width, height); 1.1045 + break; 1.1046 + case FOURCC_BGGR: 1.1047 + r = I420ToBayerBGGR(y, y_stride, 1.1048 + u, u_stride, 1.1049 + v, v_stride, 1.1050 + dst_sample, 1.1051 + dst_sample_stride ? dst_sample_stride : width, 1.1052 + width, height); 1.1053 + break; 1.1054 + case FOURCC_GBRG: 1.1055 + r = I420ToBayerGBRG(y, y_stride, 1.1056 + u, u_stride, 1.1057 + v, v_stride, 1.1058 + dst_sample, 1.1059 + dst_sample_stride ? dst_sample_stride : width, 1.1060 + width, height); 1.1061 + break; 1.1062 + case FOURCC_GRBG: 1.1063 + r = I420ToBayerGRBG(y, y_stride, 1.1064 + u, u_stride, 1.1065 + v, v_stride, 1.1066 + dst_sample, 1.1067 + dst_sample_stride ? dst_sample_stride : width, 1.1068 + width, height); 1.1069 + break; 1.1070 + case FOURCC_RGGB: 1.1071 + r = I420ToBayerRGGB(y, y_stride, 1.1072 + u, u_stride, 1.1073 + v, v_stride, 1.1074 + dst_sample, 1.1075 + dst_sample_stride ? dst_sample_stride : width, 1.1076 + width, height); 1.1077 + break; 1.1078 + case FOURCC_I400: 1.1079 + r = I400Copy(y, y_stride, 1.1080 + dst_sample, 1.1081 + dst_sample_stride ? dst_sample_stride : width, 1.1082 + width, height); 1.1083 + break; 1.1084 + case FOURCC_NV12: { 1.1085 + uint8* dst_uv = dst_sample + width * height; 1.1086 + r = I420ToNV12(y, y_stride, 1.1087 + u, u_stride, 1.1088 + v, v_stride, 1.1089 + dst_sample, 1.1090 + dst_sample_stride ? dst_sample_stride : width, 1.1091 + dst_uv, 1.1092 + dst_sample_stride ? dst_sample_stride : width, 1.1093 + width, height); 1.1094 + break; 1.1095 + } 1.1096 + case FOURCC_NV21: { 1.1097 + uint8* dst_vu = dst_sample + width * height; 1.1098 + r = I420ToNV21(y, y_stride, 1.1099 + u, u_stride, 1.1100 + v, v_stride, 1.1101 + dst_sample, 1.1102 + dst_sample_stride ? dst_sample_stride : width, 1.1103 + dst_vu, 1.1104 + dst_sample_stride ? dst_sample_stride : width, 1.1105 + width, height); 1.1106 + break; 1.1107 + } 1.1108 + // TODO(fbarchard): Add M420 and Q420. 1.1109 + // Triplanar formats 1.1110 + // TODO(fbarchard): halfstride instead of halfwidth 1.1111 + case FOURCC_I420: 1.1112 + case FOURCC_YU12: 1.1113 + case FOURCC_YV12: { 1.1114 + int halfwidth = (width + 1) / 2; 1.1115 + int halfheight = (height + 1) / 2; 1.1116 + uint8* dst_u; 1.1117 + uint8* dst_v; 1.1118 + if (format == FOURCC_YV12) { 1.1119 + dst_v = dst_sample + width * height; 1.1120 + dst_u = dst_v + halfwidth * halfheight; 1.1121 + } else { 1.1122 + dst_u = dst_sample + width * height; 1.1123 + dst_v = dst_u + halfwidth * halfheight; 1.1124 + } 1.1125 + r = I420Copy(y, y_stride, 1.1126 + u, u_stride, 1.1127 + v, v_stride, 1.1128 + dst_sample, width, 1.1129 + dst_u, halfwidth, 1.1130 + dst_v, halfwidth, 1.1131 + width, height); 1.1132 + break; 1.1133 + } 1.1134 + case FOURCC_I422: 1.1135 + case FOURCC_YV16: { 1.1136 + int halfwidth = (width + 1) / 2; 1.1137 + uint8* dst_u; 1.1138 + uint8* dst_v; 1.1139 + if (format == FOURCC_YV16) { 1.1140 + dst_v = dst_sample + width * height; 1.1141 + dst_u = dst_v + halfwidth * height; 1.1142 + } else { 1.1143 + dst_u = dst_sample + width * height; 1.1144 + dst_v = dst_u + halfwidth * height; 1.1145 + } 1.1146 + r = I420ToI422(y, y_stride, 1.1147 + u, u_stride, 1.1148 + v, v_stride, 1.1149 + dst_sample, width, 1.1150 + dst_u, halfwidth, 1.1151 + dst_v, halfwidth, 1.1152 + width, height); 1.1153 + break; 1.1154 + } 1.1155 + case FOURCC_I444: 1.1156 + case FOURCC_YV24: { 1.1157 + uint8* dst_u; 1.1158 + uint8* dst_v; 1.1159 + if (format == FOURCC_YV24) { 1.1160 + dst_v = dst_sample + width * height; 1.1161 + dst_u = dst_v + width * height; 1.1162 + } else { 1.1163 + dst_u = dst_sample + width * height; 1.1164 + dst_v = dst_u + width * height; 1.1165 + } 1.1166 + r = I420ToI444(y, y_stride, 1.1167 + u, u_stride, 1.1168 + v, v_stride, 1.1169 + dst_sample, width, 1.1170 + dst_u, width, 1.1171 + dst_v, width, 1.1172 + width, height); 1.1173 + break; 1.1174 + } 1.1175 + case FOURCC_I411: { 1.1176 + int quarterwidth = (width + 3) / 4; 1.1177 + uint8* dst_u = dst_sample + width * height; 1.1178 + uint8* dst_v = dst_u + quarterwidth * height; 1.1179 + r = I420ToI411(y, y_stride, 1.1180 + u, u_stride, 1.1181 + v, v_stride, 1.1182 + dst_sample, width, 1.1183 + dst_u, quarterwidth, 1.1184 + dst_v, quarterwidth, 1.1185 + width, height); 1.1186 + break; 1.1187 + } 1.1188 + 1.1189 + // Formats not supported - MJPG, biplanar, some rgb formats. 1.1190 + default: 1.1191 + return -1; // unknown fourcc - return failure code. 1.1192 + } 1.1193 + return r; 1.1194 +} 1.1195 + 1.1196 +#ifdef __cplusplus 1.1197 +} // extern "C" 1.1198 +} // namespace libyuv 1.1199 +#endif