1 /* 2 * Copyright 2013 The LibYuv Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 // Get PSNR or SSIM for video sequence. Assuming RAW 4:2:0 Y:Cb:Cr format 12 // To build: g++ -O3 -o psnr psnr.cc ssim.cc psnr_main.cc 13 // or VisualC: cl /Ox psnr.cc ssim.cc psnr_main.cc 14 // 15 // To enable OpenMP and SSE2 16 // gcc: g++ -msse2 -O3 -fopenmp -o psnr psnr.cc ssim.cc psnr_main.cc 17 // vc: cl /arch:SSE2 /Ox /openmp psnr.cc ssim.cc psnr_main.cc 18 // 19 // Usage: psnr org_seq rec_seq -s width height [-skip skip_org skip_rec] 20 21 #ifndef _CRT_SECURE_NO_WARNINGS 22 #define _CRT_SECURE_NO_WARNINGS 23 #endif 24 25 #include <stddef.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #ifdef _OPENMP 30 #include <omp.h> 31 #endif 32 33 #include "./psnr.h" 34 #include "./ssim.h" 35 #ifdef HAVE_JPEG 36 #include "libyuv/compare.h" 37 #include "libyuv/convert.h" 38 #endif 39 40 struct metric { 41 double y, u, v, all; 42 double min_y, min_u, min_v, min_all; 43 double global_y, global_u, global_v, global_all; 44 int min_frame; 45 }; 46 47 // options 48 bool verbose = false; 49 bool quiet = false; 50 bool show_name = false; 51 bool do_swap_uv = false; 52 bool do_psnr = false; 53 bool do_ssim = false; 54 bool do_mse = false; 55 bool do_lssim = false; 56 int image_width = 0, image_height = 0; 57 int fileindex_org = 0; // argv argument contains the source file name. 58 int fileindex_rec = 0; // argv argument contains the destination file name. 59 int num_rec = 0; 60 int num_skip_org = 0; 61 int num_skip_rec = 0; 62 int num_frames = 0; 63 #ifdef _OPENMP 64 int num_threads = 0; 65 #endif 66 67 // Parse PYUV format. ie name.1920x800_24Hz_P420.yuv 68 bool ExtractResolutionFromFilename(const char* name, 69 int* width_ptr, 70 int* height_ptr) { 71 // Isolate the .width_height. section of the filename by searching for a 72 // dot or underscore followed by a digit. 73 for (int i = 0; name[i]; ++i) { 74 if ((name[i] == '.' || name[i] == '_') && 75 name[i + 1] >= '0' && name[i + 1] <= '9') { 76 int n = sscanf(name + i + 1, "%dx%d", width_ptr, height_ptr); // NOLINT 77 if (2 == n) { 78 return true; 79 } 80 } 81 } 82 83 #ifdef HAVE_JPEG 84 // Try parsing file as a jpeg. 85 FILE* const file_org = fopen(name, "rb"); 86 if (file_org == NULL) { 87 fprintf(stderr, "Cannot open %s\n", name); 88 return false; 89 } 90 fseek(file_org, 0, SEEK_END); 91 size_t total_size = ftell(file_org); 92 fseek(file_org, 0, SEEK_SET); 93 uint8* const ch_org = new uint8[total_size]; 94 memset(ch_org, 0, total_size); 95 size_t bytes_org = fread(ch_org, sizeof(uint8), total_size, file_org); 96 fclose(file_org); 97 if (bytes_org == total_size) { 98 if (0 == libyuv::MJPGSize(ch_org, total_size, width_ptr, height_ptr)) { 99 delete[] ch_org; 100 return true; 101 } 102 } 103 delete[] ch_org; 104 #endif // HAVE_JPEG 105 return false; 106 } 107 108 // Scale Y channel from 16..240 to 0..255. 109 // This can be useful when comparing codecs that are inconsistant about Y 110 uint8 ScaleY(uint8 y) { 111 int ny = (y - 16) * 256 / 224; 112 if (ny < 0) ny = 0; 113 if (ny > 255) ny = 255; 114 return static_cast<uint8>(ny); 115 } 116 117 // MSE = Mean Square Error 118 double GetMSE(double sse, double size) { 119 return sse / size; 120 } 121 122 void PrintHelp(const char * program) { 123 printf("%s [-options] org_seq rec_seq [rec_seq2.. etc]\n", program); 124 #ifdef HAVE_JPEG 125 printf("jpeg or raw YUV 420 supported.\n"); 126 #endif 127 printf("options:\n"); 128 printf(" -s <width> <height> .... specify YUV size, mandatory if none of the " 129 "sequences have the\n"); 130 printf(" resolution embedded in their filename (ie. " 131 "name.1920x800_24Hz_P420.yuv)\n"); 132 printf(" -psnr .................. compute PSNR (default)\n"); 133 printf(" -ssim .................. compute SSIM\n"); 134 printf(" -mse ................... compute MSE\n"); 135 printf(" -swap .................. Swap U and V plane\n"); 136 printf(" -skip <org> <rec> ...... Number of frame to skip of org and rec\n"); 137 printf(" -frames <num> .......... Number of frames to compare\n"); 138 #ifdef _OPENMP 139 printf(" -t <num> ............... Number of threads\n"); 140 #endif 141 printf(" -n ..................... Show file name\n"); 142 printf(" -v ..................... verbose++\n"); 143 printf(" -q ..................... quiet\n"); 144 printf(" -h ..................... this help\n"); 145 exit(0); 146 } 147 148 void ParseOptions(int argc, const char* argv[]) { 149 if (argc <= 1) PrintHelp(argv[0]); 150 for (int c = 1; c < argc; ++c) { 151 if (!strcmp(argv[c], "-v")) { 152 verbose = true; 153 } else if (!strcmp(argv[c], "-q")) { 154 quiet = true; 155 } else if (!strcmp(argv[c], "-n")) { 156 show_name = true; 157 } else if (!strcmp(argv[c], "-psnr")) { 158 do_psnr = true; 159 } else if (!strcmp(argv[c], "-mse")) { 160 do_mse = true; 161 } else if (!strcmp(argv[c], "-ssim")) { 162 do_ssim = true; 163 } else if (!strcmp(argv[c], "-lssim")) { 164 do_ssim = true; 165 do_lssim = true; 166 } else if (!strcmp(argv[c], "-swap")) { 167 do_swap_uv = true; 168 } else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { 169 PrintHelp(argv[0]); 170 } else if (!strcmp(argv[c], "-s") && c + 2 < argc) { 171 image_width = atoi(argv[++c]); // NOLINT 172 image_height = atoi(argv[++c]); // NOLINT 173 } else if (!strcmp(argv[c], "-skip") && c + 2 < argc) { 174 num_skip_org = atoi(argv[++c]); // NOLINT 175 num_skip_rec = atoi(argv[++c]); // NOLINT 176 } else if (!strcmp(argv[c], "-frames") && c + 1 < argc) { 177 num_frames = atoi(argv[++c]); // NOLINT 178 #ifdef _OPENMP 179 } else if (!strcmp(argv[c], "-t") && c + 1 < argc) { 180 num_threads = atoi(argv[++c]); // NOLINT 181 #endif 182 } else if (argv[c][0] == '-') { 183 fprintf(stderr, "Unknown option. %s\n", argv[c]); 184 } else if (fileindex_org == 0) { 185 fileindex_org = c; 186 } else if (fileindex_rec == 0) { 187 fileindex_rec = c; 188 num_rec = 1; 189 } else { 190 ++num_rec; 191 } 192 } 193 if (fileindex_org == 0 || fileindex_rec == 0) { 194 fprintf(stderr, "Missing filenames\n"); 195 PrintHelp(argv[0]); 196 } 197 if (num_skip_org < 0 || num_skip_rec < 0) { 198 fprintf(stderr, "Skipped frames incorrect\n"); 199 PrintHelp(argv[0]); 200 } 201 if (num_frames < 0) { 202 fprintf(stderr, "Number of frames incorrect\n"); 203 PrintHelp(argv[0]); 204 } 205 if (image_width == 0 || image_height == 0) { 206 int org_width, org_height; 207 int rec_width, rec_height; 208 bool org_res_avail = ExtractResolutionFromFilename(argv[fileindex_org], 209 &org_width, 210 &org_height); 211 bool rec_res_avail = ExtractResolutionFromFilename(argv[fileindex_rec], 212 &rec_width, 213 &rec_height); 214 if (org_res_avail) { 215 if (rec_res_avail) { 216 if ((org_width == rec_width) && (org_height == rec_height)) { 217 image_width = org_width; 218 image_height = org_height; 219 } else { 220 fprintf(stderr, "Sequences have different resolutions.\n"); 221 PrintHelp(argv[0]); 222 } 223 } else { 224 image_width = org_width; 225 image_height = org_height; 226 } 227 } else if (rec_res_avail) { 228 image_width = rec_width; 229 image_height = rec_height; 230 } else { 231 fprintf(stderr, "Missing dimensions.\n"); 232 PrintHelp(argv[0]); 233 } 234 } 235 } 236 237 bool UpdateMetrics(uint8* ch_org, uint8* ch_rec, 238 const int y_size, const int uv_size, const size_t total_size, 239 int number_of_frames, 240 metric* cur_distortion_psnr, 241 metric* distorted_frame, bool do_psnr) { 242 const int uv_offset = (do_swap_uv ? uv_size : 0); 243 const uint8* const u_org = ch_org + y_size + uv_offset; 244 const uint8* const u_rec = ch_rec + y_size; 245 const uint8* const v_org = ch_org + y_size + (uv_size - uv_offset); 246 const uint8* const v_rec = ch_rec + y_size + uv_size; 247 if (do_psnr) { 248 #ifdef HAVE_JPEG 249 double y_err = static_cast<double>( 250 libyuv::ComputeSumSquareError(ch_org, ch_rec, y_size)); 251 double u_err = static_cast<double>( 252 libyuv::ComputeSumSquareError(u_org, u_rec, uv_size)); 253 double v_err = static_cast<double>( 254 libyuv::ComputeSumSquareError(v_org, v_rec, uv_size)); 255 #else 256 double y_err = ComputeSumSquareError(ch_org, ch_rec, y_size); 257 double u_err = ComputeSumSquareError(u_org, u_rec, uv_size); 258 double v_err = ComputeSumSquareError(v_org, v_rec, uv_size); 259 #endif 260 const double total_err = y_err + u_err + v_err; 261 cur_distortion_psnr->global_y += y_err; 262 cur_distortion_psnr->global_u += u_err; 263 cur_distortion_psnr->global_v += v_err; 264 cur_distortion_psnr->global_all += total_err; 265 distorted_frame->y = ComputePSNR(y_err, static_cast<double>(y_size)); 266 distorted_frame->u = ComputePSNR(u_err, static_cast<double>(uv_size)); 267 distorted_frame->v = ComputePSNR(v_err, static_cast<double>(uv_size)); 268 distorted_frame->all = ComputePSNR(total_err, 269 static_cast<double>(total_size)); 270 } else { 271 distorted_frame->y = CalcSSIM(ch_org, ch_rec, image_width, image_height); 272 distorted_frame->u = CalcSSIM(u_org, u_rec, (image_width + 1) / 2, 273 (image_height + 1) / 2); 274 distorted_frame->v = CalcSSIM(v_org, v_rec, (image_width + 1) / 2, 275 (image_height + 1) / 2); 276 distorted_frame->all = 277 (distorted_frame->y + distorted_frame->u + distorted_frame->v) 278 / total_size; 279 distorted_frame->y /= y_size; 280 distorted_frame->u /= uv_size; 281 distorted_frame->v /= uv_size; 282 283 if (do_lssim) { 284 distorted_frame->all = CalcLSSIM(distorted_frame->all); 285 distorted_frame->y = CalcLSSIM(distorted_frame->y); 286 distorted_frame->u = CalcLSSIM(distorted_frame->u); 287 distorted_frame->v = CalcLSSIM(distorted_frame->v); 288 } 289 } 290 291 cur_distortion_psnr->y += distorted_frame->y; 292 cur_distortion_psnr->u += distorted_frame->u; 293 cur_distortion_psnr->v += distorted_frame->v; 294 cur_distortion_psnr->all += distorted_frame->all; 295 296 bool ismin = false; 297 if (distorted_frame->y < cur_distortion_psnr->min_y) 298 cur_distortion_psnr->min_y = distorted_frame->y; 299 if (distorted_frame->u < cur_distortion_psnr->min_u) 300 cur_distortion_psnr->min_u = distorted_frame->u; 301 if (distorted_frame->v < cur_distortion_psnr->min_v) 302 cur_distortion_psnr->min_v = distorted_frame->v; 303 if (distorted_frame->all < cur_distortion_psnr->min_all) { 304 cur_distortion_psnr->min_all = distorted_frame->all; 305 cur_distortion_psnr->min_frame = number_of_frames; 306 ismin = true; 307 } 308 return ismin; 309 } 310 311 int main(int argc, const char* argv[]) { 312 ParseOptions(argc, argv); 313 if (!do_psnr && !do_ssim) { 314 do_psnr = true; 315 } 316 317 #ifdef _OPENMP 318 if (num_threads) { 319 omp_set_num_threads(num_threads); 320 } 321 if (verbose) { 322 printf("OpenMP %d procs\n", omp_get_num_procs()); 323 } 324 #endif 325 // Open original file (first file argument) 326 FILE* const file_org = fopen(argv[fileindex_org], "rb"); 327 if (file_org == NULL) { 328 fprintf(stderr, "Cannot open %s\n", argv[fileindex_org]); 329 exit(1); 330 } 331 332 // Open all files to compare to 333 FILE** file_rec = new FILE* [num_rec]; 334 memset(file_rec, 0, num_rec * sizeof(FILE*)); // NOLINT 335 for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) { 336 file_rec[cur_rec] = fopen(argv[fileindex_rec + cur_rec], "rb"); 337 if (file_rec[cur_rec] == NULL) { 338 fprintf(stderr, "Cannot open %s\n", argv[fileindex_rec + cur_rec]); 339 fclose(file_org); 340 for (int i = 0; i < cur_rec; ++i) { 341 fclose(file_rec[i]); 342 } 343 delete[] file_rec; 344 exit(1); 345 } 346 } 347 348 const int y_size = image_width * image_height; 349 const int uv_size = ((image_width + 1) / 2) * ((image_height + 1) / 2); 350 const size_t total_size = y_size + 2 * uv_size; // NOLINT 351 #if defined(_MSC_VER) 352 _fseeki64(file_org, 353 static_cast<__int64>(num_skip_org) * 354 static_cast<__int64>(total_size), SEEK_SET); 355 #else 356 fseek(file_org, num_skip_org * total_size, SEEK_SET); 357 #endif 358 for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) { 359 #if defined(_MSC_VER) 360 _fseeki64(file_rec[cur_rec], 361 static_cast<__int64>(num_skip_rec) * 362 static_cast<__int64>(total_size), 363 SEEK_SET); 364 #else 365 fseek(file_rec[cur_rec], num_skip_rec * total_size, SEEK_SET); 366 #endif 367 } 368 369 uint8* const ch_org = new uint8[total_size]; 370 uint8* const ch_rec = new uint8[total_size]; 371 if (ch_org == NULL || ch_rec == NULL) { 372 fprintf(stderr, "No memory available\n"); 373 fclose(file_org); 374 for (int i = 0; i < num_rec; ++i) { 375 fclose(file_rec[i]); 376 } 377 delete[] ch_org; 378 delete[] ch_rec; 379 delete[] file_rec; 380 exit(1); 381 } 382 383 metric* const distortion_psnr = new metric[num_rec]; 384 metric* const distortion_ssim = new metric[num_rec]; 385 for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) { 386 metric* cur_distortion_psnr = &distortion_psnr[cur_rec]; 387 cur_distortion_psnr->y = 0.0; 388 cur_distortion_psnr->u = 0.0; 389 cur_distortion_psnr->v = 0.0; 390 cur_distortion_psnr->all = 0.0; 391 cur_distortion_psnr->min_y = kMaxPSNR; 392 cur_distortion_psnr->min_u = kMaxPSNR; 393 cur_distortion_psnr->min_v = kMaxPSNR; 394 cur_distortion_psnr->min_all = kMaxPSNR; 395 cur_distortion_psnr->min_frame = 0; 396 cur_distortion_psnr->global_y = 0.0; 397 cur_distortion_psnr->global_u = 0.0; 398 cur_distortion_psnr->global_v = 0.0; 399 cur_distortion_psnr->global_all = 0.0; 400 distortion_ssim[cur_rec] = cur_distortion_psnr[cur_rec]; 401 } 402 403 if (verbose) { 404 printf("Size: %dx%d\n", image_width, image_height); 405 } 406 407 if (!quiet) { 408 printf("Frame"); 409 if (do_psnr) { 410 printf("\t PSNR-Y \t PSNR-U \t PSNR-V \t PSNR-All \t Frame"); 411 } 412 if (do_ssim) { 413 printf("\t SSIM-Y\t SSIM-U\t SSIM-V\t SSIM-All\t Frame"); 414 } 415 if (show_name) { 416 printf("\tName\n"); 417 } else { 418 printf("\n"); 419 } 420 } 421 422 int number_of_frames; 423 for (number_of_frames = 0; ; ++number_of_frames) { 424 if (num_frames && number_of_frames >= num_frames) 425 break; 426 427 size_t bytes_org = fread(ch_org, sizeof(uint8), total_size, file_org); 428 if (bytes_org < total_size) { 429 #ifdef HAVE_JPEG 430 // Try parsing file as a jpeg. 431 uint8* const ch_jpeg = new uint8[bytes_org]; 432 memcpy(ch_jpeg, ch_org, bytes_org); 433 memset(ch_org, 0, total_size); 434 435 if (0 != libyuv::MJPGToI420(ch_jpeg, bytes_org, 436 ch_org, 437 image_width, 438 ch_org + y_size, 439 (image_width + 1) / 2, 440 ch_org + y_size + uv_size, 441 (image_width + 1) / 2, 442 image_width, 443 image_height, 444 image_width, 445 image_height)) { 446 delete[] ch_jpeg; 447 break; 448 } 449 delete[] ch_jpeg; 450 #else 451 break; 452 #endif // HAVE_JPEG 453 } 454 455 for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) { 456 size_t bytes_rec = fread(ch_rec, sizeof(uint8), 457 total_size, file_rec[cur_rec]); 458 if (bytes_rec < total_size) { 459 #ifdef HAVE_JPEG 460 // Try parsing file as a jpeg. 461 uint8* const ch_jpeg = new uint8[bytes_rec]; 462 memcpy(ch_jpeg, ch_rec, bytes_rec); 463 memset(ch_rec, 0, total_size); 464 465 if (0 != libyuv::MJPGToI420(ch_jpeg, bytes_rec, 466 ch_rec, 467 image_width, 468 ch_rec + y_size, 469 (image_width + 1) / 2, 470 ch_rec + y_size + uv_size, 471 (image_width + 1) / 2, 472 image_width, 473 image_height, 474 image_width, 475 image_height)) { 476 delete[] ch_jpeg; 477 break; 478 } 479 delete[] ch_jpeg; 480 #else 481 break; 482 #endif // HAVE_JPEG 483 } 484 485 if (verbose) { 486 printf("%5d", number_of_frames); 487 } 488 if (do_psnr) { 489 metric distorted_frame; 490 metric* cur_distortion_psnr = &distortion_psnr[cur_rec]; 491 bool ismin = UpdateMetrics(ch_org, ch_rec, 492 y_size, uv_size, total_size, 493 number_of_frames, 494 cur_distortion_psnr, 495 &distorted_frame, true); 496 if (verbose) { 497 printf("\t%10.6f", distorted_frame.y); 498 printf("\t%10.6f", distorted_frame.u); 499 printf("\t%10.6f", distorted_frame.v); 500 printf("\t%10.6f", distorted_frame.all); 501 printf("\t%5s", ismin ? "min" : ""); 502 } 503 } 504 if (do_ssim) { 505 metric distorted_frame; 506 metric* cur_distortion_ssim = &distortion_ssim[cur_rec]; 507 bool ismin = UpdateMetrics(ch_org, ch_rec, 508 y_size, uv_size, total_size, 509 number_of_frames, 510 cur_distortion_ssim, 511 &distorted_frame, false); 512 if (verbose) { 513 printf("\t%10.6f", distorted_frame.y); 514 printf("\t%10.6f", distorted_frame.u); 515 printf("\t%10.6f", distorted_frame.v); 516 printf("\t%10.6f", distorted_frame.all); 517 printf("\t%5s", ismin ? "min" : ""); 518 } 519 } 520 if (verbose) { 521 if (show_name) { 522 printf("\t%s", argv[fileindex_rec + cur_rec]); 523 } 524 printf("\n"); 525 } 526 } 527 } 528 529 // Final PSNR computation. 530 for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) { 531 metric* cur_distortion_psnr = &distortion_psnr[cur_rec]; 532 metric* cur_distortion_ssim = &distortion_ssim[cur_rec]; 533 if (number_of_frames > 0) { 534 const double norm = 1. / static_cast<double>(number_of_frames); 535 cur_distortion_psnr->y *= norm; 536 cur_distortion_psnr->u *= norm; 537 cur_distortion_psnr->v *= norm; 538 cur_distortion_psnr->all *= norm; 539 cur_distortion_ssim->y *= norm; 540 cur_distortion_ssim->u *= norm; 541 cur_distortion_ssim->v *= norm; 542 cur_distortion_ssim->all *= norm; 543 } 544 545 if (do_psnr) { 546 const double global_psnr_y = ComputePSNR( 547 cur_distortion_psnr->global_y, 548 static_cast<double>(y_size) * number_of_frames); 549 const double global_psnr_u = ComputePSNR( 550 cur_distortion_psnr->global_u, 551 static_cast<double>(uv_size) * number_of_frames); 552 const double global_psnr_v = ComputePSNR( 553 cur_distortion_psnr->global_v, 554 static_cast<double>(uv_size) * number_of_frames); 555 const double global_psnr_all = ComputePSNR( 556 cur_distortion_psnr->global_all, 557 static_cast<double>(total_size) * number_of_frames); 558 printf("Global:\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d", 559 global_psnr_y, 560 global_psnr_u, 561 global_psnr_v, 562 global_psnr_all, 563 number_of_frames); 564 if (show_name) { 565 printf("\t%s", argv[fileindex_rec + cur_rec]); 566 } 567 printf("\n"); 568 } 569 570 if (!quiet) { 571 printf("Avg:"); 572 if (do_psnr) { 573 printf("\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d", 574 cur_distortion_psnr->y, 575 cur_distortion_psnr->u, 576 cur_distortion_psnr->v, 577 cur_distortion_psnr->all, 578 number_of_frames); 579 } 580 if (do_ssim) { 581 printf("\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d", 582 cur_distortion_ssim->y, 583 cur_distortion_ssim->u, 584 cur_distortion_ssim->v, 585 cur_distortion_ssim->all, 586 number_of_frames); 587 } 588 if (show_name) { 589 printf("\t%s", argv[fileindex_rec + cur_rec]); 590 } 591 printf("\n"); 592 } 593 if (!quiet) { 594 printf("Min:"); 595 if (do_psnr) { 596 printf("\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d", 597 cur_distortion_psnr->min_y, 598 cur_distortion_psnr->min_u, 599 cur_distortion_psnr->min_v, 600 cur_distortion_psnr->min_all, 601 cur_distortion_psnr->min_frame); 602 } 603 if (do_ssim) { 604 printf("\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d", 605 cur_distortion_ssim->min_y, 606 cur_distortion_ssim->min_u, 607 cur_distortion_ssim->min_v, 608 cur_distortion_ssim->min_all, 609 cur_distortion_ssim->min_frame); 610 } 611 if (show_name) { 612 printf("\t%s", argv[fileindex_rec + cur_rec]); 613 } 614 printf("\n"); 615 } 616 617 if (do_mse) { 618 double global_mse_y = GetMSE(cur_distortion_psnr->global_y, 619 static_cast<double>(y_size) * number_of_frames); 620 double global_mse_u = GetMSE(cur_distortion_psnr->global_u, 621 static_cast<double>(uv_size) * number_of_frames); 622 double global_mse_v = GetMSE(cur_distortion_psnr->global_v, 623 static_cast<double>(uv_size) * number_of_frames); 624 double global_mse_all = GetMSE(cur_distortion_psnr->global_all, 625 static_cast<double>(total_size) * number_of_frames); 626 printf("MSE:\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d", 627 global_mse_y, 628 global_mse_u, 629 global_mse_v, 630 global_mse_all, 631 number_of_frames); 632 if (show_name) { 633 printf("\t%s", argv[fileindex_rec + cur_rec]); 634 } 635 printf("\n"); 636 } 637 } 638 fclose(file_org); 639 for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) { 640 fclose(file_rec[cur_rec]); 641 } 642 delete[] distortion_psnr; 643 delete[] distortion_ssim; 644 delete[] ch_org; 645 delete[] ch_rec; 646 delete[] file_rec; 647 return 0; 648 } 649