media/libyuv/util/convert.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /*
michael@0 2 * Copyright 2013 The LibYuv Project Authors. All rights reserved.
michael@0 3 *
michael@0 4 * Use of this source code is governed by a BSD-style license
michael@0 5 * that can be found in the LICENSE file in the root of the source
michael@0 6 * tree. An additional intellectual property rights grant can be found
michael@0 7 * in the file PATENTS. All contributing project authors may
michael@0 8 * be found in the AUTHORS file in the root of the source tree.
michael@0 9 */
michael@0 10
michael@0 11 // Convert an ARGB image to YUV.
michael@0 12 // Usage: convert src_argb.raw dst_yuv.raw
michael@0 13
michael@0 14 #ifndef _CRT_SECURE_NO_WARNINGS
michael@0 15 #define _CRT_SECURE_NO_WARNINGS
michael@0 16 #endif
michael@0 17
michael@0 18 #include <stddef.h>
michael@0 19 #include <stdio.h>
michael@0 20 #include <stdlib.h>
michael@0 21 #include <string.h>
michael@0 22
michael@0 23 #include "libyuv/convert.h"
michael@0 24 #include "libyuv/planar_functions.h"
michael@0 25 #include "libyuv/scale_argb.h"
michael@0 26
michael@0 27 // options
michael@0 28 bool verbose = false;
michael@0 29 bool attenuate = false;
michael@0 30 bool unattenuate = false;
michael@0 31 int image_width = 0, image_height = 0; // original width and height
michael@0 32 int dst_width = 0, dst_height = 0; // new width and height
michael@0 33 int fileindex_org = 0; // argv argument contains the original file name.
michael@0 34 int fileindex_rec = 0; // argv argument contains the reconstructed file name.
michael@0 35 int num_rec = 0; // Number of reconstructed images.
michael@0 36 int num_skip_org = 0; // Number of frames to skip in original.
michael@0 37 int num_frames = 0; // Number of frames to convert.
michael@0 38 int filter = 1; // Bilinear filter for scaling.
michael@0 39
michael@0 40 static __inline uint32 Abs(int32 v) {
michael@0 41 return v >= 0 ? v : -v;
michael@0 42 }
michael@0 43
michael@0 44 // Parse PYUV format. ie name.1920x800_24Hz_P420.yuv
michael@0 45 bool ExtractResolutionFromFilename(const char* name,
michael@0 46 int* width_ptr,
michael@0 47 int* height_ptr) {
michael@0 48 // Isolate the .width_height. section of the filename by searching for a
michael@0 49 // dot or underscore followed by a digit.
michael@0 50 for (int i = 0; name[i]; ++i) {
michael@0 51 if ((name[i] == '.' || name[i] == '_') &&
michael@0 52 name[i + 1] >= '0' && name[i + 1] <= '9') {
michael@0 53 int n = sscanf(name + i + 1, "%dx%d", width_ptr, height_ptr); // NOLINT
michael@0 54 if (2 == n) {
michael@0 55 return true;
michael@0 56 }
michael@0 57 }
michael@0 58 }
michael@0 59 return false;
michael@0 60 }
michael@0 61
michael@0 62 void PrintHelp(const char * program) {
michael@0 63 printf("%s [-options] src_argb.raw dst_yuv.raw\n", program);
michael@0 64 printf(" -s <width> <height> .... specify source resolution. "
michael@0 65 "Optional if name contains\n"
michael@0 66 " resolution (ie. "
michael@0 67 "name.1920x800_24Hz_P420.yuv)\n"
michael@0 68 " Negative value mirrors.\n");
michael@0 69 printf(" -d <width> <height> .... specify destination resolution.\n");
michael@0 70 printf(" -f <filter> ............ 0 = point, 1 = bilinear (default).\n");
michael@0 71 printf(" -skip <src_argb> ....... Number of frame to skip of src_argb\n");
michael@0 72 printf(" -frames <num> .......... Number of frames to convert\n");
michael@0 73 printf(" -attenuate ............. Attenuate the ARGB image\n");
michael@0 74 printf(" -unattenuate ........... Unattenuate the ARGB image\n");
michael@0 75 printf(" -v ..................... verbose\n");
michael@0 76 printf(" -h ..................... this help\n");
michael@0 77 exit(0);
michael@0 78 }
michael@0 79
michael@0 80 void ParseOptions(int argc, const char* argv[]) {
michael@0 81 if (argc <= 1) PrintHelp(argv[0]);
michael@0 82 for (int c = 1; c < argc; ++c) {
michael@0 83 if (!strcmp(argv[c], "-v")) {
michael@0 84 verbose = true;
michael@0 85 } else if (!strcmp(argv[c], "-attenuate")) {
michael@0 86 attenuate = true;
michael@0 87 } else if (!strcmp(argv[c], "-unattenuate")) {
michael@0 88 unattenuate = true;
michael@0 89 } else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
michael@0 90 PrintHelp(argv[0]);
michael@0 91 } else if (!strcmp(argv[c], "-s") && c + 2 < argc) {
michael@0 92 image_width = atoi(argv[++c]); // NOLINT
michael@0 93 image_height = atoi(argv[++c]); // NOLINT
michael@0 94 } else if (!strcmp(argv[c], "-d") && c + 2 < argc) {
michael@0 95 dst_width = atoi(argv[++c]); // NOLINT
michael@0 96 dst_height = atoi(argv[++c]); // NOLINT
michael@0 97 } else if (!strcmp(argv[c], "-skip") && c + 1 < argc) {
michael@0 98 num_skip_org = atoi(argv[++c]); // NOLINT
michael@0 99 } else if (!strcmp(argv[c], "-frames") && c + 1 < argc) {
michael@0 100 num_frames = atoi(argv[++c]); // NOLINT
michael@0 101 } else if (!strcmp(argv[c], "-f") && c + 1 < argc) {
michael@0 102 filter = atoi(argv[++c]); // NOLINT
michael@0 103 } else if (argv[c][0] == '-') {
michael@0 104 fprintf(stderr, "Unknown option. %s\n", argv[c]);
michael@0 105 } else if (fileindex_org == 0) {
michael@0 106 fileindex_org = c;
michael@0 107 } else if (fileindex_rec == 0) {
michael@0 108 fileindex_rec = c;
michael@0 109 num_rec = 1;
michael@0 110 } else {
michael@0 111 ++num_rec;
michael@0 112 }
michael@0 113 }
michael@0 114 if (fileindex_org == 0 || fileindex_rec == 0) {
michael@0 115 fprintf(stderr, "Missing filenames\n");
michael@0 116 PrintHelp(argv[0]);
michael@0 117 }
michael@0 118 if (num_skip_org < 0) {
michael@0 119 fprintf(stderr, "Skipped frames incorrect\n");
michael@0 120 PrintHelp(argv[0]);
michael@0 121 }
michael@0 122 if (num_frames < 0) {
michael@0 123 fprintf(stderr, "Number of frames incorrect\n");
michael@0 124 PrintHelp(argv[0]);
michael@0 125 }
michael@0 126
michael@0 127 int org_width, org_height;
michael@0 128 int rec_width, rec_height;
michael@0 129 bool org_res_avail = ExtractResolutionFromFilename(argv[fileindex_org],
michael@0 130 &org_width,
michael@0 131 &org_height);
michael@0 132 bool rec_res_avail = ExtractResolutionFromFilename(argv[fileindex_rec],
michael@0 133 &rec_width,
michael@0 134 &rec_height);
michael@0 135 if (image_width == 0 || image_height == 0) {
michael@0 136 if (org_res_avail) {
michael@0 137 image_width = org_width;
michael@0 138 image_height = org_height;
michael@0 139 } else if (rec_res_avail) {
michael@0 140 image_width = rec_width;
michael@0 141 image_height = rec_height;
michael@0 142 } else {
michael@0 143 fprintf(stderr, "Missing dimensions.\n");
michael@0 144 PrintHelp(argv[0]);
michael@0 145 }
michael@0 146 }
michael@0 147 if (dst_width == 0 || dst_height == 0) {
michael@0 148 if (rec_res_avail) {
michael@0 149 dst_width = rec_width;
michael@0 150 dst_height = rec_height;
michael@0 151 } else {
michael@0 152 dst_width = Abs(image_width);
michael@0 153 dst_height = Abs(image_height);
michael@0 154 }
michael@0 155 }
michael@0 156 }
michael@0 157
michael@0 158 static const int kTileX = 32;
michael@0 159 static const int kTileY = 32;
michael@0 160
michael@0 161 static int TileARGBScale(const uint8* src_argb, int src_stride_argb,
michael@0 162 int src_width, int src_height,
michael@0 163 uint8* dst_argb, int dst_stride_argb,
michael@0 164 int dst_width, int dst_height,
michael@0 165 libyuv::FilterMode filtering) {
michael@0 166 for (int y = 0; y < dst_height; y += kTileY) {
michael@0 167 for (int x = 0; x < dst_width; x += kTileX) {
michael@0 168 int clip_width = kTileX;
michael@0 169 if (x + clip_width > dst_width) {
michael@0 170 clip_width = dst_width - x;
michael@0 171 }
michael@0 172 int clip_height = kTileY;
michael@0 173 if (y + clip_height > dst_height) {
michael@0 174 clip_height = dst_height - y;
michael@0 175 }
michael@0 176 int r = libyuv::ARGBScaleClip(src_argb, src_stride_argb,
michael@0 177 src_width, src_height,
michael@0 178 dst_argb, dst_stride_argb,
michael@0 179 dst_width, dst_height,
michael@0 180 x, y, clip_width, clip_height, filtering);
michael@0 181 if (r) {
michael@0 182 return r;
michael@0 183 }
michael@0 184 }
michael@0 185 }
michael@0 186 return 0;
michael@0 187 }
michael@0 188
michael@0 189 int main(int argc, const char* argv[]) {
michael@0 190 ParseOptions(argc, argv);
michael@0 191
michael@0 192 // Open original file (first file argument)
michael@0 193 FILE* const file_org = fopen(argv[fileindex_org], "rb");
michael@0 194 if (file_org == NULL) {
michael@0 195 fprintf(stderr, "Cannot open %s\n", argv[fileindex_org]);
michael@0 196 exit(1);
michael@0 197 }
michael@0 198
michael@0 199 // Open all files to convert to
michael@0 200 FILE** file_rec = new FILE* [num_rec];
michael@0 201 memset(file_rec, 0, num_rec * sizeof(FILE*)); // NOLINT
michael@0 202 for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) {
michael@0 203 file_rec[cur_rec] = fopen(argv[fileindex_rec + cur_rec], "wb");
michael@0 204 if (file_rec[cur_rec] == NULL) {
michael@0 205 fprintf(stderr, "Cannot open %s\n", argv[fileindex_rec + cur_rec]);
michael@0 206 fclose(file_org);
michael@0 207 for (int i = 0; i < cur_rec; ++i) {
michael@0 208 fclose(file_rec[i]);
michael@0 209 }
michael@0 210 delete[] file_rec;
michael@0 211 exit(1);
michael@0 212 }
michael@0 213 }
michael@0 214
michael@0 215 bool org_is_yuv = strstr(argv[fileindex_org], "_P420.") != NULL;
michael@0 216 bool org_is_argb = strstr(argv[fileindex_org], "_ARGB.") != NULL;
michael@0 217 if (!org_is_yuv && !org_is_argb) {
michael@0 218 fprintf(stderr, "Original format unknown %s\n", argv[fileindex_org]);
michael@0 219 exit(1);
michael@0 220 }
michael@0 221 int org_size = Abs(image_width) * Abs(image_height) * 4; // ARGB
michael@0 222 // Input is YUV
michael@0 223 if (org_is_yuv) {
michael@0 224 const int y_size = Abs(image_width) * Abs(image_height);
michael@0 225 const int uv_size = ((Abs(image_width) + 1) / 2) *
michael@0 226 ((Abs(image_height) + 1) / 2);
michael@0 227 org_size = y_size + 2 * uv_size; // YUV original.
michael@0 228 }
michael@0 229
michael@0 230 const int dst_size = dst_width * dst_height * 4; // ARGB scaled
michael@0 231 const int y_size = dst_width * dst_height;
michael@0 232 const int uv_size = ((dst_width + 1) / 2) * ((dst_height + 1) / 2);
michael@0 233 const size_t total_size = y_size + 2 * uv_size;
michael@0 234 #if defined(_MSC_VER)
michael@0 235 _fseeki64(file_org,
michael@0 236 static_cast<__int64>(num_skip_org) *
michael@0 237 static_cast<__int64>(org_size), SEEK_SET);
michael@0 238 #else
michael@0 239 fseek(file_org, num_skip_org * total_size, SEEK_SET);
michael@0 240 #endif
michael@0 241
michael@0 242 uint8* const ch_org = new uint8[org_size];
michael@0 243 uint8* const ch_dst = new uint8[dst_size];
michael@0 244 uint8* const ch_rec = new uint8[total_size];
michael@0 245 if (ch_org == NULL || ch_rec == NULL) {
michael@0 246 fprintf(stderr, "No memory available\n");
michael@0 247 fclose(file_org);
michael@0 248 for (int i = 0; i < num_rec; ++i) {
michael@0 249 fclose(file_rec[i]);
michael@0 250 }
michael@0 251 delete[] ch_org;
michael@0 252 delete[] ch_dst;
michael@0 253 delete[] ch_rec;
michael@0 254 delete[] file_rec;
michael@0 255 exit(1);
michael@0 256 }
michael@0 257
michael@0 258 if (verbose) {
michael@0 259 printf("Size: %dx%d to %dx%d\n", image_width, image_height,
michael@0 260 dst_width, dst_height);
michael@0 261 }
michael@0 262
michael@0 263 int number_of_frames;
michael@0 264 for (number_of_frames = 0; ; ++number_of_frames) {
michael@0 265 if (num_frames && number_of_frames >= num_frames)
michael@0 266 break;
michael@0 267
michael@0 268 // Load original YUV or ARGB frame.
michael@0 269 size_t bytes_org = fread(ch_org, sizeof(uint8),
michael@0 270 static_cast<size_t>(org_size), file_org);
michael@0 271 if (bytes_org < static_cast<size_t>(org_size))
michael@0 272 break;
michael@0 273
michael@0 274 // TODO(fbarchard): Attenuate doesnt need to know dimensions.
michael@0 275 // ARGB attenuate frame
michael@0 276 if (org_is_argb && attenuate) {
michael@0 277 libyuv::ARGBAttenuate(ch_org, 0, ch_org, 0, org_size / 4, 1);
michael@0 278 }
michael@0 279 // ARGB unattenuate frame
michael@0 280 if (org_is_argb && unattenuate) {
michael@0 281 libyuv::ARGBUnattenuate(ch_org, 0, ch_org, 0, org_size / 4, 1);
michael@0 282 }
michael@0 283
michael@0 284 for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) {
michael@0 285 // Scale YUV or ARGB frame.
michael@0 286 if (org_is_yuv) {
michael@0 287 int src_width = Abs(image_width);
michael@0 288 int src_height = Abs(image_height);
michael@0 289 int half_src_width = (src_width + 1) / 2;
michael@0 290 int half_src_height = (src_height + 1) / 2;
michael@0 291 int half_dst_width = (dst_width + 1) / 2;
michael@0 292 int half_dst_height = (dst_height + 1) / 2;
michael@0 293 I420Scale(ch_org, src_width,
michael@0 294 ch_org + src_width * src_height, half_src_width,
michael@0 295 ch_org + src_width * src_height +
michael@0 296 half_src_width * half_src_height, half_src_width,
michael@0 297 image_width, image_height,
michael@0 298 ch_rec, dst_width,
michael@0 299 ch_rec + dst_width * dst_height, half_dst_width,
michael@0 300 ch_rec + dst_width * dst_height +
michael@0 301 half_dst_width * half_dst_height, half_dst_width,
michael@0 302 dst_width, dst_height,
michael@0 303 static_cast<libyuv::FilterMode>(filter));
michael@0 304 } else {
michael@0 305 TileARGBScale(ch_org, Abs(image_width) * 4,
michael@0 306 image_width, image_height,
michael@0 307 ch_dst, dst_width * 4,
michael@0 308 dst_width, dst_height,
michael@0 309 static_cast<libyuv::FilterMode>(filter));
michael@0 310 }
michael@0 311 bool rec_is_yuv = strstr(argv[fileindex_rec + cur_rec], "_P420.") != NULL;
michael@0 312 bool rec_is_argb =
michael@0 313 strstr(argv[fileindex_rec + cur_rec], "_ARGB.") != NULL;
michael@0 314 if (!rec_is_yuv && !rec_is_argb) {
michael@0 315 fprintf(stderr, "Output format unknown %s\n",
michael@0 316 argv[fileindex_rec + cur_rec]);
michael@0 317 continue; // Advance to next file.
michael@0 318 }
michael@0 319
michael@0 320 // Convert ARGB to YUV.
michael@0 321 if (!org_is_yuv && rec_is_yuv) {
michael@0 322 int half_width = (dst_width + 1) / 2;
michael@0 323 int half_height = (dst_height + 1) / 2;
michael@0 324 libyuv::ARGBToI420(ch_dst, dst_width * 4,
michael@0 325 ch_rec, dst_width,
michael@0 326 ch_rec + dst_width * dst_height, half_width,
michael@0 327 ch_rec + dst_width * dst_height +
michael@0 328 half_width * half_height, half_width,
michael@0 329 dst_width, dst_height);
michael@0 330 }
michael@0 331
michael@0 332 // Output YUV or ARGB frame.
michael@0 333 if (rec_is_yuv) {
michael@0 334 size_t bytes_rec = fwrite(ch_rec, sizeof(uint8),
michael@0 335 static_cast<size_t>(total_size),
michael@0 336 file_rec[cur_rec]);
michael@0 337 if (bytes_rec < static_cast<size_t>(total_size))
michael@0 338 break;
michael@0 339 } else {
michael@0 340 size_t bytes_rec = fwrite(ch_dst, sizeof(uint8),
michael@0 341 static_cast<size_t>(dst_size),
michael@0 342 file_rec[cur_rec]);
michael@0 343 if (bytes_rec < static_cast<size_t>(dst_size))
michael@0 344 break;
michael@0 345 }
michael@0 346 if (verbose) {
michael@0 347 printf("%5d", number_of_frames);
michael@0 348 }
michael@0 349 if (verbose) {
michael@0 350 printf("\t%s", argv[fileindex_rec + cur_rec]);
michael@0 351 printf("\n");
michael@0 352 }
michael@0 353 }
michael@0 354 }
michael@0 355
michael@0 356 fclose(file_org);
michael@0 357 for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) {
michael@0 358 fclose(file_rec[cur_rec]);
michael@0 359 }
michael@0 360 delete[] ch_org;
michael@0 361 delete[] ch_dst;
michael@0 362 delete[] ch_rec;
michael@0 363 delete[] file_rec;
michael@0 364 return 0;
michael@0 365 }

mercurial