1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libyuv/source/convert_to_argb.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,327 @@ 1.4 +/* 1.5 + * Copyright 2011 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_argb.h" 1.15 + 1.16 +#include "libyuv/cpu_id.h" 1.17 +#include "libyuv/format_conversion.h" 1.18 +#ifdef HAVE_JPEG 1.19 +#include "libyuv/mjpeg_decoder.h" 1.20 +#endif 1.21 +#include "libyuv/rotate_argb.h" 1.22 +#include "libyuv/row.h" 1.23 +#include "libyuv/video_common.h" 1.24 + 1.25 +#ifdef __cplusplus 1.26 +namespace libyuv { 1.27 +extern "C" { 1.28 +#endif 1.29 + 1.30 +// Convert camera sample to I420 with cropping, rotation and vertical flip. 1.31 +// src_width is used for source stride computation 1.32 +// src_height is used to compute location of planes, and indicate inversion 1.33 +// sample_size is measured in bytes and is the size of the frame. 1.34 +// With MJPEG it is the compressed size of the frame. 1.35 +LIBYUV_API 1.36 +int ConvertToARGB(const uint8* sample, size_t sample_size, 1.37 + uint8* crop_argb, int argb_stride, 1.38 + int crop_x, int crop_y, 1.39 + int src_width, int src_height, 1.40 + int crop_width, int crop_height, 1.41 + enum RotationMode rotation, 1.42 + uint32 fourcc) { 1.43 + uint32 format = CanonicalFourCC(fourcc); 1.44 + int aligned_src_width = (src_width + 1) & ~1; 1.45 + const uint8* src; 1.46 + const uint8* src_uv; 1.47 + int abs_src_height = (src_height < 0) ? -src_height : src_height; 1.48 + int inv_crop_height = (crop_height < 0) ? -crop_height : crop_height; 1.49 + int r = 0; 1.50 + 1.51 + // One pass rotation is available for some formats. For the rest, convert 1.52 + // to I420 (with optional vertical flipping) into a temporary I420 buffer, 1.53 + // and then rotate the I420 to the final destination buffer. 1.54 + // For in-place conversion, if destination crop_argb is same as source sample, 1.55 + // also enable temporary buffer. 1.56 + LIBYUV_BOOL need_buf = (rotation && format != FOURCC_ARGB) || 1.57 + crop_argb == sample; 1.58 + uint8* tmp_argb = crop_argb; 1.59 + int tmp_argb_stride = argb_stride; 1.60 + uint8* rotate_buffer = NULL; 1.61 + int abs_crop_height = (crop_height < 0) ? -crop_height : crop_height; 1.62 + 1.63 + if (crop_argb == NULL || sample == NULL || 1.64 + src_width <= 0 || crop_width <= 0 || 1.65 + src_height == 0 || crop_height == 0) { 1.66 + return -1; 1.67 + } 1.68 + if (src_height < 0) { 1.69 + inv_crop_height = -inv_crop_height; 1.70 + } 1.71 + 1.72 + if (need_buf) { 1.73 + int argb_size = crop_width * abs_crop_height * 4; 1.74 + rotate_buffer = (uint8*)malloc(argb_size); 1.75 + if (!rotate_buffer) { 1.76 + return 1; // Out of memory runtime error. 1.77 + } 1.78 + crop_argb = rotate_buffer; 1.79 + argb_stride = crop_width; 1.80 + } 1.81 + 1.82 + switch (format) { 1.83 + // Single plane formats 1.84 + case FOURCC_YUY2: 1.85 + src = sample + (aligned_src_width * crop_y + crop_x) * 2; 1.86 + r = YUY2ToARGB(src, aligned_src_width * 2, 1.87 + crop_argb, argb_stride, 1.88 + crop_width, inv_crop_height); 1.89 + break; 1.90 + case FOURCC_UYVY: 1.91 + src = sample + (aligned_src_width * crop_y + crop_x) * 2; 1.92 + r = UYVYToARGB(src, aligned_src_width * 2, 1.93 + crop_argb, argb_stride, 1.94 + crop_width, inv_crop_height); 1.95 + break; 1.96 + case FOURCC_24BG: 1.97 + src = sample + (src_width * crop_y + crop_x) * 3; 1.98 + r = RGB24ToARGB(src, src_width * 3, 1.99 + crop_argb, argb_stride, 1.100 + crop_width, inv_crop_height); 1.101 + break; 1.102 + case FOURCC_RAW: 1.103 + src = sample + (src_width * crop_y + crop_x) * 3; 1.104 + r = RAWToARGB(src, src_width * 3, 1.105 + crop_argb, argb_stride, 1.106 + crop_width, inv_crop_height); 1.107 + break; 1.108 + case FOURCC_ARGB: 1.109 + src = sample + (src_width * crop_y + crop_x) * 4; 1.110 + r = ARGBToARGB(src, src_width * 4, 1.111 + crop_argb, argb_stride, 1.112 + crop_width, inv_crop_height); 1.113 + break; 1.114 + case FOURCC_BGRA: 1.115 + src = sample + (src_width * crop_y + crop_x) * 4; 1.116 + r = BGRAToARGB(src, src_width * 4, 1.117 + crop_argb, argb_stride, 1.118 + crop_width, inv_crop_height); 1.119 + break; 1.120 + case FOURCC_ABGR: 1.121 + src = sample + (src_width * crop_y + crop_x) * 4; 1.122 + r = ABGRToARGB(src, src_width * 4, 1.123 + crop_argb, argb_stride, 1.124 + crop_width, inv_crop_height); 1.125 + break; 1.126 + case FOURCC_RGBA: 1.127 + src = sample + (src_width * crop_y + crop_x) * 4; 1.128 + r = RGBAToARGB(src, src_width * 4, 1.129 + crop_argb, argb_stride, 1.130 + crop_width, inv_crop_height); 1.131 + break; 1.132 + case FOURCC_RGBP: 1.133 + src = sample + (src_width * crop_y + crop_x) * 2; 1.134 + r = RGB565ToARGB(src, src_width * 2, 1.135 + crop_argb, argb_stride, 1.136 + crop_width, inv_crop_height); 1.137 + break; 1.138 + case FOURCC_RGBO: 1.139 + src = sample + (src_width * crop_y + crop_x) * 2; 1.140 + r = ARGB1555ToARGB(src, src_width * 2, 1.141 + crop_argb, argb_stride, 1.142 + crop_width, inv_crop_height); 1.143 + break; 1.144 + case FOURCC_R444: 1.145 + src = sample + (src_width * crop_y + crop_x) * 2; 1.146 + r = ARGB4444ToARGB(src, src_width * 2, 1.147 + crop_argb, argb_stride, 1.148 + crop_width, inv_crop_height); 1.149 + break; 1.150 + // TODO(fbarchard): Support cropping Bayer by odd numbers 1.151 + // by adjusting fourcc. 1.152 + case FOURCC_BGGR: 1.153 + src = sample + (src_width * crop_y + crop_x); 1.154 + r = BayerBGGRToARGB(src, src_width, 1.155 + crop_argb, argb_stride, 1.156 + crop_width, inv_crop_height); 1.157 + break; 1.158 + 1.159 + case FOURCC_GBRG: 1.160 + src = sample + (src_width * crop_y + crop_x); 1.161 + r = BayerGBRGToARGB(src, src_width, 1.162 + crop_argb, argb_stride, 1.163 + crop_width, inv_crop_height); 1.164 + break; 1.165 + 1.166 + case FOURCC_GRBG: 1.167 + src = sample + (src_width * crop_y + crop_x); 1.168 + r = BayerGRBGToARGB(src, src_width, 1.169 + crop_argb, argb_stride, 1.170 + crop_width, inv_crop_height); 1.171 + break; 1.172 + 1.173 + case FOURCC_RGGB: 1.174 + src = sample + (src_width * crop_y + crop_x); 1.175 + r = BayerRGGBToARGB(src, src_width, 1.176 + crop_argb, argb_stride, 1.177 + crop_width, inv_crop_height); 1.178 + break; 1.179 + 1.180 + case FOURCC_I400: 1.181 + src = sample + src_width * crop_y + crop_x; 1.182 + r = I400ToARGB(src, src_width, 1.183 + crop_argb, argb_stride, 1.184 + crop_width, inv_crop_height); 1.185 + break; 1.186 + 1.187 + // Biplanar formats 1.188 + case FOURCC_NV12: 1.189 + src = sample + (src_width * crop_y + crop_x); 1.190 + src_uv = sample + aligned_src_width * (src_height + crop_y / 2) + crop_x; 1.191 + r = NV12ToARGB(src, src_width, 1.192 + src_uv, aligned_src_width, 1.193 + crop_argb, argb_stride, 1.194 + crop_width, inv_crop_height); 1.195 + break; 1.196 + case FOURCC_NV21: 1.197 + src = sample + (src_width * crop_y + crop_x); 1.198 + src_uv = sample + aligned_src_width * (src_height + crop_y / 2) + crop_x; 1.199 + // Call NV12 but with u and v parameters swapped. 1.200 + r = NV21ToARGB(src, src_width, 1.201 + src_uv, aligned_src_width, 1.202 + crop_argb, argb_stride, 1.203 + crop_width, inv_crop_height); 1.204 + break; 1.205 + case FOURCC_M420: 1.206 + src = sample + (src_width * crop_y) * 12 / 8 + crop_x; 1.207 + r = M420ToARGB(src, src_width, 1.208 + crop_argb, argb_stride, 1.209 + crop_width, inv_crop_height); 1.210 + break; 1.211 +// case FOURCC_Q420: 1.212 +// src = sample + (src_width + aligned_src_width * 2) * crop_y + crop_x; 1.213 +// src_uv = sample + (src_width + aligned_src_width * 2) * crop_y + 1.214 +// src_width + crop_x * 2; 1.215 +// r = Q420ToARGB(src, src_width * 3, 1.216 +// src_uv, src_width * 3, 1.217 +// crop_argb, argb_stride, 1.218 +// crop_width, inv_crop_height); 1.219 +// break; 1.220 + // Triplanar formats 1.221 + case FOURCC_I420: 1.222 + case FOURCC_YU12: 1.223 + case FOURCC_YV12: { 1.224 + const uint8* src_y = sample + (src_width * crop_y + crop_x); 1.225 + const uint8* src_u; 1.226 + const uint8* src_v; 1.227 + int halfwidth = (src_width + 1) / 2; 1.228 + int halfheight = (abs_src_height + 1) / 2; 1.229 + if (format == FOURCC_YV12) { 1.230 + src_v = sample + src_width * abs_src_height + 1.231 + (halfwidth * crop_y + crop_x) / 2; 1.232 + src_u = sample + src_width * abs_src_height + 1.233 + halfwidth * (halfheight + crop_y / 2) + crop_x / 2; 1.234 + } else { 1.235 + src_u = sample + src_width * abs_src_height + 1.236 + (halfwidth * crop_y + crop_x) / 2; 1.237 + src_v = sample + src_width * abs_src_height + 1.238 + halfwidth * (halfheight + crop_y / 2) + crop_x / 2; 1.239 + } 1.240 + r = I420ToARGB(src_y, src_width, 1.241 + src_u, halfwidth, 1.242 + src_v, halfwidth, 1.243 + crop_argb, argb_stride, 1.244 + crop_width, inv_crop_height); 1.245 + break; 1.246 + } 1.247 + case FOURCC_I422: 1.248 + case FOURCC_YV16: { 1.249 + const uint8* src_y = sample + src_width * crop_y + crop_x; 1.250 + const uint8* src_u; 1.251 + const uint8* src_v; 1.252 + int halfwidth = (src_width + 1) / 2; 1.253 + if (format == FOURCC_YV16) { 1.254 + src_v = sample + src_width * abs_src_height + 1.255 + halfwidth * crop_y + crop_x / 2; 1.256 + src_u = sample + src_width * abs_src_height + 1.257 + halfwidth * (abs_src_height + crop_y) + crop_x / 2; 1.258 + } else { 1.259 + src_u = sample + src_width * abs_src_height + 1.260 + halfwidth * crop_y + crop_x / 2; 1.261 + src_v = sample + src_width * abs_src_height + 1.262 + halfwidth * (abs_src_height + crop_y) + crop_x / 2; 1.263 + } 1.264 + r = I422ToARGB(src_y, src_width, 1.265 + src_u, halfwidth, 1.266 + src_v, halfwidth, 1.267 + crop_argb, argb_stride, 1.268 + crop_width, inv_crop_height); 1.269 + break; 1.270 + } 1.271 + case FOURCC_I444: 1.272 + case FOURCC_YV24: { 1.273 + const uint8* src_y = sample + src_width * crop_y + crop_x; 1.274 + const uint8* src_u; 1.275 + const uint8* src_v; 1.276 + if (format == FOURCC_YV24) { 1.277 + src_v = sample + src_width * (abs_src_height + crop_y) + crop_x; 1.278 + src_u = sample + src_width * (abs_src_height * 2 + crop_y) + crop_x; 1.279 + } else { 1.280 + src_u = sample + src_width * (abs_src_height + crop_y) + crop_x; 1.281 + src_v = sample + src_width * (abs_src_height * 2 + crop_y) + crop_x; 1.282 + } 1.283 + r = I444ToARGB(src_y, src_width, 1.284 + src_u, src_width, 1.285 + src_v, src_width, 1.286 + crop_argb, argb_stride, 1.287 + crop_width, inv_crop_height); 1.288 + break; 1.289 + } 1.290 + case FOURCC_I411: { 1.291 + int quarterwidth = (src_width + 3) / 4; 1.292 + const uint8* src_y = sample + src_width * crop_y + crop_x; 1.293 + const uint8* src_u = sample + src_width * abs_src_height + 1.294 + quarterwidth * crop_y + crop_x / 4; 1.295 + const uint8* src_v = sample + src_width * abs_src_height + 1.296 + quarterwidth * (abs_src_height + crop_y) + crop_x / 4; 1.297 + r = I411ToARGB(src_y, src_width, 1.298 + src_u, quarterwidth, 1.299 + src_v, quarterwidth, 1.300 + crop_argb, argb_stride, 1.301 + crop_width, inv_crop_height); 1.302 + break; 1.303 + } 1.304 +#ifdef HAVE_JPEG 1.305 + case FOURCC_MJPG: 1.306 + r = MJPGToARGB(sample, sample_size, 1.307 + crop_argb, argb_stride, 1.308 + src_width, abs_src_height, crop_width, inv_crop_height); 1.309 + break; 1.310 +#endif 1.311 + default: 1.312 + r = -1; // unknown fourcc - return failure code. 1.313 + } 1.314 + 1.315 + if (need_buf) { 1.316 + if (!r) { 1.317 + r = ARGBRotate(crop_argb, argb_stride, 1.318 + tmp_argb, tmp_argb_stride, 1.319 + crop_width, abs_crop_height, rotation); 1.320 + } 1.321 + free(rotate_buffer); 1.322 + } 1.323 + 1.324 + return r; 1.325 +} 1.326 + 1.327 +#ifdef __cplusplus 1.328 +} // extern "C" 1.329 +} // namespace libyuv 1.330 +#endif