1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libyuv/util/convert.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,365 @@ 1.4 +/* 1.5 + * Copyright 2013 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 +// Convert an ARGB image to YUV. 1.15 +// Usage: convert src_argb.raw dst_yuv.raw 1.16 + 1.17 +#ifndef _CRT_SECURE_NO_WARNINGS 1.18 +#define _CRT_SECURE_NO_WARNINGS 1.19 +#endif 1.20 + 1.21 +#include <stddef.h> 1.22 +#include <stdio.h> 1.23 +#include <stdlib.h> 1.24 +#include <string.h> 1.25 + 1.26 +#include "libyuv/convert.h" 1.27 +#include "libyuv/planar_functions.h" 1.28 +#include "libyuv/scale_argb.h" 1.29 + 1.30 +// options 1.31 +bool verbose = false; 1.32 +bool attenuate = false; 1.33 +bool unattenuate = false; 1.34 +int image_width = 0, image_height = 0; // original width and height 1.35 +int dst_width = 0, dst_height = 0; // new width and height 1.36 +int fileindex_org = 0; // argv argument contains the original file name. 1.37 +int fileindex_rec = 0; // argv argument contains the reconstructed file name. 1.38 +int num_rec = 0; // Number of reconstructed images. 1.39 +int num_skip_org = 0; // Number of frames to skip in original. 1.40 +int num_frames = 0; // Number of frames to convert. 1.41 +int filter = 1; // Bilinear filter for scaling. 1.42 + 1.43 +static __inline uint32 Abs(int32 v) { 1.44 + return v >= 0 ? v : -v; 1.45 +} 1.46 + 1.47 +// Parse PYUV format. ie name.1920x800_24Hz_P420.yuv 1.48 +bool ExtractResolutionFromFilename(const char* name, 1.49 + int* width_ptr, 1.50 + int* height_ptr) { 1.51 + // Isolate the .width_height. section of the filename by searching for a 1.52 + // dot or underscore followed by a digit. 1.53 + for (int i = 0; name[i]; ++i) { 1.54 + if ((name[i] == '.' || name[i] == '_') && 1.55 + name[i + 1] >= '0' && name[i + 1] <= '9') { 1.56 + int n = sscanf(name + i + 1, "%dx%d", width_ptr, height_ptr); // NOLINT 1.57 + if (2 == n) { 1.58 + return true; 1.59 + } 1.60 + } 1.61 + } 1.62 + return false; 1.63 +} 1.64 + 1.65 +void PrintHelp(const char * program) { 1.66 + printf("%s [-options] src_argb.raw dst_yuv.raw\n", program); 1.67 + printf(" -s <width> <height> .... specify source resolution. " 1.68 + "Optional if name contains\n" 1.69 + " resolution (ie. " 1.70 + "name.1920x800_24Hz_P420.yuv)\n" 1.71 + " Negative value mirrors.\n"); 1.72 + printf(" -d <width> <height> .... specify destination resolution.\n"); 1.73 + printf(" -f <filter> ............ 0 = point, 1 = bilinear (default).\n"); 1.74 + printf(" -skip <src_argb> ....... Number of frame to skip of src_argb\n"); 1.75 + printf(" -frames <num> .......... Number of frames to convert\n"); 1.76 + printf(" -attenuate ............. Attenuate the ARGB image\n"); 1.77 + printf(" -unattenuate ........... Unattenuate the ARGB image\n"); 1.78 + printf(" -v ..................... verbose\n"); 1.79 + printf(" -h ..................... this help\n"); 1.80 + exit(0); 1.81 +} 1.82 + 1.83 +void ParseOptions(int argc, const char* argv[]) { 1.84 + if (argc <= 1) PrintHelp(argv[0]); 1.85 + for (int c = 1; c < argc; ++c) { 1.86 + if (!strcmp(argv[c], "-v")) { 1.87 + verbose = true; 1.88 + } else if (!strcmp(argv[c], "-attenuate")) { 1.89 + attenuate = true; 1.90 + } else if (!strcmp(argv[c], "-unattenuate")) { 1.91 + unattenuate = true; 1.92 + } else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { 1.93 + PrintHelp(argv[0]); 1.94 + } else if (!strcmp(argv[c], "-s") && c + 2 < argc) { 1.95 + image_width = atoi(argv[++c]); // NOLINT 1.96 + image_height = atoi(argv[++c]); // NOLINT 1.97 + } else if (!strcmp(argv[c], "-d") && c + 2 < argc) { 1.98 + dst_width = atoi(argv[++c]); // NOLINT 1.99 + dst_height = atoi(argv[++c]); // NOLINT 1.100 + } else if (!strcmp(argv[c], "-skip") && c + 1 < argc) { 1.101 + num_skip_org = atoi(argv[++c]); // NOLINT 1.102 + } else if (!strcmp(argv[c], "-frames") && c + 1 < argc) { 1.103 + num_frames = atoi(argv[++c]); // NOLINT 1.104 + } else if (!strcmp(argv[c], "-f") && c + 1 < argc) { 1.105 + filter = atoi(argv[++c]); // NOLINT 1.106 + } else if (argv[c][0] == '-') { 1.107 + fprintf(stderr, "Unknown option. %s\n", argv[c]); 1.108 + } else if (fileindex_org == 0) { 1.109 + fileindex_org = c; 1.110 + } else if (fileindex_rec == 0) { 1.111 + fileindex_rec = c; 1.112 + num_rec = 1; 1.113 + } else { 1.114 + ++num_rec; 1.115 + } 1.116 + } 1.117 + if (fileindex_org == 0 || fileindex_rec == 0) { 1.118 + fprintf(stderr, "Missing filenames\n"); 1.119 + PrintHelp(argv[0]); 1.120 + } 1.121 + if (num_skip_org < 0) { 1.122 + fprintf(stderr, "Skipped frames incorrect\n"); 1.123 + PrintHelp(argv[0]); 1.124 + } 1.125 + if (num_frames < 0) { 1.126 + fprintf(stderr, "Number of frames incorrect\n"); 1.127 + PrintHelp(argv[0]); 1.128 + } 1.129 + 1.130 + int org_width, org_height; 1.131 + int rec_width, rec_height; 1.132 + bool org_res_avail = ExtractResolutionFromFilename(argv[fileindex_org], 1.133 + &org_width, 1.134 + &org_height); 1.135 + bool rec_res_avail = ExtractResolutionFromFilename(argv[fileindex_rec], 1.136 + &rec_width, 1.137 + &rec_height); 1.138 + if (image_width == 0 || image_height == 0) { 1.139 + if (org_res_avail) { 1.140 + image_width = org_width; 1.141 + image_height = org_height; 1.142 + } else if (rec_res_avail) { 1.143 + image_width = rec_width; 1.144 + image_height = rec_height; 1.145 + } else { 1.146 + fprintf(stderr, "Missing dimensions.\n"); 1.147 + PrintHelp(argv[0]); 1.148 + } 1.149 + } 1.150 + if (dst_width == 0 || dst_height == 0) { 1.151 + if (rec_res_avail) { 1.152 + dst_width = rec_width; 1.153 + dst_height = rec_height; 1.154 + } else { 1.155 + dst_width = Abs(image_width); 1.156 + dst_height = Abs(image_height); 1.157 + } 1.158 + } 1.159 +} 1.160 + 1.161 +static const int kTileX = 32; 1.162 +static const int kTileY = 32; 1.163 + 1.164 +static int TileARGBScale(const uint8* src_argb, int src_stride_argb, 1.165 + int src_width, int src_height, 1.166 + uint8* dst_argb, int dst_stride_argb, 1.167 + int dst_width, int dst_height, 1.168 + libyuv::FilterMode filtering) { 1.169 + for (int y = 0; y < dst_height; y += kTileY) { 1.170 + for (int x = 0; x < dst_width; x += kTileX) { 1.171 + int clip_width = kTileX; 1.172 + if (x + clip_width > dst_width) { 1.173 + clip_width = dst_width - x; 1.174 + } 1.175 + int clip_height = kTileY; 1.176 + if (y + clip_height > dst_height) { 1.177 + clip_height = dst_height - y; 1.178 + } 1.179 + int r = libyuv::ARGBScaleClip(src_argb, src_stride_argb, 1.180 + src_width, src_height, 1.181 + dst_argb, dst_stride_argb, 1.182 + dst_width, dst_height, 1.183 + x, y, clip_width, clip_height, filtering); 1.184 + if (r) { 1.185 + return r; 1.186 + } 1.187 + } 1.188 + } 1.189 + return 0; 1.190 +} 1.191 + 1.192 +int main(int argc, const char* argv[]) { 1.193 + ParseOptions(argc, argv); 1.194 + 1.195 + // Open original file (first file argument) 1.196 + FILE* const file_org = fopen(argv[fileindex_org], "rb"); 1.197 + if (file_org == NULL) { 1.198 + fprintf(stderr, "Cannot open %s\n", argv[fileindex_org]); 1.199 + exit(1); 1.200 + } 1.201 + 1.202 + // Open all files to convert to 1.203 + FILE** file_rec = new FILE* [num_rec]; 1.204 + memset(file_rec, 0, num_rec * sizeof(FILE*)); // NOLINT 1.205 + for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) { 1.206 + file_rec[cur_rec] = fopen(argv[fileindex_rec + cur_rec], "wb"); 1.207 + if (file_rec[cur_rec] == NULL) { 1.208 + fprintf(stderr, "Cannot open %s\n", argv[fileindex_rec + cur_rec]); 1.209 + fclose(file_org); 1.210 + for (int i = 0; i < cur_rec; ++i) { 1.211 + fclose(file_rec[i]); 1.212 + } 1.213 + delete[] file_rec; 1.214 + exit(1); 1.215 + } 1.216 + } 1.217 + 1.218 + bool org_is_yuv = strstr(argv[fileindex_org], "_P420.") != NULL; 1.219 + bool org_is_argb = strstr(argv[fileindex_org], "_ARGB.") != NULL; 1.220 + if (!org_is_yuv && !org_is_argb) { 1.221 + fprintf(stderr, "Original format unknown %s\n", argv[fileindex_org]); 1.222 + exit(1); 1.223 + } 1.224 + int org_size = Abs(image_width) * Abs(image_height) * 4; // ARGB 1.225 + // Input is YUV 1.226 + if (org_is_yuv) { 1.227 + const int y_size = Abs(image_width) * Abs(image_height); 1.228 + const int uv_size = ((Abs(image_width) + 1) / 2) * 1.229 + ((Abs(image_height) + 1) / 2); 1.230 + org_size = y_size + 2 * uv_size; // YUV original. 1.231 + } 1.232 + 1.233 + const int dst_size = dst_width * dst_height * 4; // ARGB scaled 1.234 + const int y_size = dst_width * dst_height; 1.235 + const int uv_size = ((dst_width + 1) / 2) * ((dst_height + 1) / 2); 1.236 + const size_t total_size = y_size + 2 * uv_size; 1.237 +#if defined(_MSC_VER) 1.238 + _fseeki64(file_org, 1.239 + static_cast<__int64>(num_skip_org) * 1.240 + static_cast<__int64>(org_size), SEEK_SET); 1.241 +#else 1.242 + fseek(file_org, num_skip_org * total_size, SEEK_SET); 1.243 +#endif 1.244 + 1.245 + uint8* const ch_org = new uint8[org_size]; 1.246 + uint8* const ch_dst = new uint8[dst_size]; 1.247 + uint8* const ch_rec = new uint8[total_size]; 1.248 + if (ch_org == NULL || ch_rec == NULL) { 1.249 + fprintf(stderr, "No memory available\n"); 1.250 + fclose(file_org); 1.251 + for (int i = 0; i < num_rec; ++i) { 1.252 + fclose(file_rec[i]); 1.253 + } 1.254 + delete[] ch_org; 1.255 + delete[] ch_dst; 1.256 + delete[] ch_rec; 1.257 + delete[] file_rec; 1.258 + exit(1); 1.259 + } 1.260 + 1.261 + if (verbose) { 1.262 + printf("Size: %dx%d to %dx%d\n", image_width, image_height, 1.263 + dst_width, dst_height); 1.264 + } 1.265 + 1.266 + int number_of_frames; 1.267 + for (number_of_frames = 0; ; ++number_of_frames) { 1.268 + if (num_frames && number_of_frames >= num_frames) 1.269 + break; 1.270 + 1.271 + // Load original YUV or ARGB frame. 1.272 + size_t bytes_org = fread(ch_org, sizeof(uint8), 1.273 + static_cast<size_t>(org_size), file_org); 1.274 + if (bytes_org < static_cast<size_t>(org_size)) 1.275 + break; 1.276 + 1.277 + // TODO(fbarchard): Attenuate doesnt need to know dimensions. 1.278 + // ARGB attenuate frame 1.279 + if (org_is_argb && attenuate) { 1.280 + libyuv::ARGBAttenuate(ch_org, 0, ch_org, 0, org_size / 4, 1); 1.281 + } 1.282 + // ARGB unattenuate frame 1.283 + if (org_is_argb && unattenuate) { 1.284 + libyuv::ARGBUnattenuate(ch_org, 0, ch_org, 0, org_size / 4, 1); 1.285 + } 1.286 + 1.287 + for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) { 1.288 + // Scale YUV or ARGB frame. 1.289 + if (org_is_yuv) { 1.290 + int src_width = Abs(image_width); 1.291 + int src_height = Abs(image_height); 1.292 + int half_src_width = (src_width + 1) / 2; 1.293 + int half_src_height = (src_height + 1) / 2; 1.294 + int half_dst_width = (dst_width + 1) / 2; 1.295 + int half_dst_height = (dst_height + 1) / 2; 1.296 + I420Scale(ch_org, src_width, 1.297 + ch_org + src_width * src_height, half_src_width, 1.298 + ch_org + src_width * src_height + 1.299 + half_src_width * half_src_height, half_src_width, 1.300 + image_width, image_height, 1.301 + ch_rec, dst_width, 1.302 + ch_rec + dst_width * dst_height, half_dst_width, 1.303 + ch_rec + dst_width * dst_height + 1.304 + half_dst_width * half_dst_height, half_dst_width, 1.305 + dst_width, dst_height, 1.306 + static_cast<libyuv::FilterMode>(filter)); 1.307 + } else { 1.308 + TileARGBScale(ch_org, Abs(image_width) * 4, 1.309 + image_width, image_height, 1.310 + ch_dst, dst_width * 4, 1.311 + dst_width, dst_height, 1.312 + static_cast<libyuv::FilterMode>(filter)); 1.313 + } 1.314 + bool rec_is_yuv = strstr(argv[fileindex_rec + cur_rec], "_P420.") != NULL; 1.315 + bool rec_is_argb = 1.316 + strstr(argv[fileindex_rec + cur_rec], "_ARGB.") != NULL; 1.317 + if (!rec_is_yuv && !rec_is_argb) { 1.318 + fprintf(stderr, "Output format unknown %s\n", 1.319 + argv[fileindex_rec + cur_rec]); 1.320 + continue; // Advance to next file. 1.321 + } 1.322 + 1.323 + // Convert ARGB to YUV. 1.324 + if (!org_is_yuv && rec_is_yuv) { 1.325 + int half_width = (dst_width + 1) / 2; 1.326 + int half_height = (dst_height + 1) / 2; 1.327 + libyuv::ARGBToI420(ch_dst, dst_width * 4, 1.328 + ch_rec, dst_width, 1.329 + ch_rec + dst_width * dst_height, half_width, 1.330 + ch_rec + dst_width * dst_height + 1.331 + half_width * half_height, half_width, 1.332 + dst_width, dst_height); 1.333 + } 1.334 + 1.335 + // Output YUV or ARGB frame. 1.336 + if (rec_is_yuv) { 1.337 + size_t bytes_rec = fwrite(ch_rec, sizeof(uint8), 1.338 + static_cast<size_t>(total_size), 1.339 + file_rec[cur_rec]); 1.340 + if (bytes_rec < static_cast<size_t>(total_size)) 1.341 + break; 1.342 + } else { 1.343 + size_t bytes_rec = fwrite(ch_dst, sizeof(uint8), 1.344 + static_cast<size_t>(dst_size), 1.345 + file_rec[cur_rec]); 1.346 + if (bytes_rec < static_cast<size_t>(dst_size)) 1.347 + break; 1.348 + } 1.349 + if (verbose) { 1.350 + printf("%5d", number_of_frames); 1.351 + } 1.352 + if (verbose) { 1.353 + printf("\t%s", argv[fileindex_rec + cur_rec]); 1.354 + printf("\n"); 1.355 + } 1.356 + } 1.357 + } 1.358 + 1.359 + fclose(file_org); 1.360 + for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) { 1.361 + fclose(file_rec[cur_rec]); 1.362 + } 1.363 + delete[] ch_org; 1.364 + delete[] ch_dst; 1.365 + delete[] ch_rec; 1.366 + delete[] file_rec; 1.367 + return 0; 1.368 +}