psnr_main.cc 20.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 *  Copyright 2013 The LibYuv Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS. All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

// Get PSNR or SSIM for video sequence. Assuming RAW 4:2:0 Y:Cb:Cr format
// To build: g++ -O3 -o psnr psnr.cc ssim.cc psnr_main.cc
// or VisualC: cl /Ox psnr.cc ssim.cc psnr_main.cc
//
// To enable OpenMP and SSE2
// gcc: g++ -msse2 -O3 -fopenmp -o psnr psnr.cc ssim.cc psnr_main.cc
// vc:  cl /arch:SSE2 /Ox /openmp psnr.cc ssim.cc psnr_main.cc
//
// Usage: psnr org_seq rec_seq -s width height [-skip skip_org skip_rec]

21
#ifndef _CRT_SECURE_NO_WARNINGS
22
#define _CRT_SECURE_NO_WARNINGS
23
#endif
24 25 26 27 28 29 30 31 32 33 34

#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _OPENMP
#include <omp.h>
#endif

#include "./psnr.h"
#include "./ssim.h"
35
#ifdef HAVE_JPEG
36
#include "libyuv/compare.h"
37 38
#include "libyuv/convert.h"
#endif
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56

struct metric {
  double y, u, v, all;
  double min_y, min_u, min_v, min_all;
  double global_y, global_u, global_v, global_all;
  int min_frame;
};

// options
bool verbose = false;
bool quiet = false;
bool show_name = false;
bool do_swap_uv = false;
bool do_psnr = false;
bool do_ssim = false;
bool do_mse = false;
bool do_lssim = false;
int image_width = 0, image_height = 0;
57 58
int fileindex_org = 0;  // argv argument contains the source file name.
int fileindex_rec = 0;  // argv argument contains the destination file name.
59 60 61 62
int num_rec = 0;
int num_skip_org = 0;
int num_skip_rec = 0;
int num_frames = 0;
63
#ifdef _OPENMP
64
int num_threads = 0;
65
#endif
66

67 68 69 70 71 72 73
// Parse PYUV format. ie name.1920x800_24Hz_P420.yuv
bool ExtractResolutionFromFilename(const char* name,
                                   int* width_ptr,
                                   int* height_ptr) {
  // Isolate the .width_height. section of the filename by searching for a
  // dot or underscore followed by a digit.
  for (int i = 0; name[i]; ++i) {
Frank Barchard's avatar
Frank Barchard committed
74 75
    if ((name[i] == '.' || name[i] == '_') && name[i + 1] >= '0' &&
        name[i + 1] <= '9') {
76 77 78 79
      int n = sscanf(name + i + 1, "%dx%d", width_ptr, height_ptr);  // NOLINT
      if (2 == n) {
        return true;
      }
80 81
    }
  }
82 83 84 85 86 87 88 89 90

#ifdef HAVE_JPEG
  // Try parsing file as a jpeg.
  FILE* const file_org = fopen(name, "rb");
  if (file_org == NULL) {
    fprintf(stderr, "Cannot open %s\n", name);
    return false;
  }
  fseek(file_org, 0, SEEK_END);
Frank Barchard's avatar
Frank Barchard committed
91
  size_t total_size = ftell(file_org);
92
  fseek(file_org, 0, SEEK_SET);
Frank Barchard's avatar
Frank Barchard committed
93
  uint8_t* const ch_org = new uint8_t[total_size];
94
  memset(ch_org, 0, total_size);
Frank Barchard's avatar
Frank Barchard committed
95
  size_t bytes_org = fread(ch_org, sizeof(uint8_t), total_size, file_org);
96 97 98 99 100 101 102 103 104
  fclose(file_org);
  if (bytes_org == total_size) {
    if (0 == libyuv::MJPGSize(ch_org, total_size, width_ptr, height_ptr)) {
      delete[] ch_org;
      return true;
    }
  }
  delete[] ch_org;
#endif  // HAVE_JPEG
105
  return false;
106 107 108 109
}

// Scale Y channel from 16..240 to 0..255.
// This can be useful when comparing codecs that are inconsistant about Y
Frank Barchard's avatar
Frank Barchard committed
110
uint8_t ScaleY(uint8_t y) {
111
  int ny = (y - 16) * 256 / 224;
112
  if (ny < 0) {
Frank Barchard's avatar
Frank Barchard committed
113
    ny = 0;
114 115
  }
  if (ny > 255) {
Frank Barchard's avatar
Frank Barchard committed
116
    ny = 255;
117
  }
Frank Barchard's avatar
Frank Barchard committed
118
  return static_cast<uint8_t>(ny);
119 120 121 122 123 124 125
}

// MSE = Mean Square Error
double GetMSE(double sse, double size) {
  return sse / size;
}

Frank Barchard's avatar
Frank Barchard committed
126
void PrintHelp(const char* program) {
127
  printf("%s [-options] org_seq rec_seq [rec_seq2.. etc]\n", program);
128 129 130
#ifdef HAVE_JPEG
  printf("jpeg or raw YUV 420 supported.\n");
#endif
131
  printf("options:\n");
Frank Barchard's avatar
Frank Barchard committed
132 133 134 135 136 137
  printf(
      " -s <width> <height> .... specify YUV size, mandatory if none of the "
      "sequences have the\n");
  printf(
      "                          resolution embedded in their filename (ie. "
      "name.1920x800_24Hz_P420.yuv)\n");
138 139 140 141 142 143
  printf(" -psnr .................. compute PSNR (default)\n");
  printf(" -ssim .................. compute SSIM\n");
  printf(" -mse ................... compute MSE\n");
  printf(" -swap .................. Swap U and V plane\n");
  printf(" -skip <org> <rec> ...... Number of frame to skip of org and rec\n");
  printf(" -frames <num> .......... Number of frames to compare\n");
144
#ifdef _OPENMP
145
  printf(" -t <num> ............... Number of threads\n");
146
#endif
147 148 149 150 151 152 153
  printf(" -n ..................... Show file name\n");
  printf(" -v ..................... verbose++\n");
  printf(" -q ..................... quiet\n");
  printf(" -h ..................... this help\n");
  exit(0);
}

154
void ParseOptions(int argc, const char* argv[]) {
155
  if (argc <= 1) {
Frank Barchard's avatar
Frank Barchard committed
156
    PrintHelp(argv[0]);
157
  }
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
  for (int c = 1; c < argc; ++c) {
    if (!strcmp(argv[c], "-v")) {
      verbose = true;
    } else if (!strcmp(argv[c], "-q")) {
      quiet = true;
    } else if (!strcmp(argv[c], "-n")) {
      show_name = true;
    } else if (!strcmp(argv[c], "-psnr")) {
      do_psnr = true;
    } else if (!strcmp(argv[c], "-mse")) {
      do_mse = true;
    } else if (!strcmp(argv[c], "-ssim")) {
      do_ssim = true;
    } else if (!strcmp(argv[c], "-lssim")) {
      do_ssim = true;
      do_lssim = true;
    } else if (!strcmp(argv[c], "-swap")) {
      do_swap_uv = true;
    } else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) {
      PrintHelp(argv[0]);
    } else if (!strcmp(argv[c], "-s") && c + 2 < argc) {
Frank Barchard's avatar
Frank Barchard committed
179 180
      image_width = atoi(argv[++c]);   // NOLINT
      image_height = atoi(argv[++c]);  // NOLINT
181
    } else if (!strcmp(argv[c], "-skip") && c + 2 < argc) {
Frank Barchard's avatar
Frank Barchard committed
182 183
      num_skip_org = atoi(argv[++c]);  // NOLINT
      num_skip_rec = atoi(argv[++c]);  // NOLINT
184
    } else if (!strcmp(argv[c], "-frames") && c + 1 < argc) {
Frank Barchard's avatar
Frank Barchard committed
185
      num_frames = atoi(argv[++c]);  // NOLINT
186
#ifdef _OPENMP
187
    } else if (!strcmp(argv[c], "-t") && c + 1 < argc) {
Frank Barchard's avatar
Frank Barchard committed
188
      num_threads = atoi(argv[++c]);  // NOLINT
189
#endif
190 191
    } else if (argv[c][0] == '-') {
      fprintf(stderr, "Unknown option. %s\n", argv[c]);
192 193 194 195 196 197 198 199 200 201
    } else if (fileindex_org == 0) {
      fileindex_org = c;
    } else if (fileindex_rec == 0) {
      fileindex_rec = c;
      num_rec = 1;
    } else {
      ++num_rec;
    }
  }
  if (fileindex_org == 0 || fileindex_rec == 0) {
202
    fprintf(stderr, "Missing filenames\n");
203 204 205
    PrintHelp(argv[0]);
  }
  if (num_skip_org < 0 || num_skip_rec < 0) {
206
    fprintf(stderr, "Skipped frames incorrect\n");
207 208 209
    PrintHelp(argv[0]);
  }
  if (num_frames < 0) {
210
    fprintf(stderr, "Number of frames incorrect\n");
211 212
    PrintHelp(argv[0]);
  }
213
  if (image_width == 0 || image_height == 0) {
214 215
    int org_width, org_height;
    int rec_width, rec_height;
216
    bool org_res_avail = ExtractResolutionFromFilename(argv[fileindex_org],
Frank Barchard's avatar
Frank Barchard committed
217
                                                       &org_width, &org_height);
218
    bool rec_res_avail = ExtractResolutionFromFilename(argv[fileindex_rec],
Frank Barchard's avatar
Frank Barchard committed
219
                                                       &rec_width, &rec_height);
220 221 222 223 224 225
    if (org_res_avail) {
      if (rec_res_avail) {
        if ((org_width == rec_width) && (org_height == rec_height)) {
          image_width = org_width;
          image_height = org_height;
        } else {
226
          fprintf(stderr, "Sequences have different resolutions.\n");
227 228 229 230 231 232 233 234 235 236
          PrintHelp(argv[0]);
        }
      } else {
        image_width = org_width;
        image_height = org_height;
      }
    } else if (rec_res_avail) {
      image_width = rec_width;
      image_height = rec_height;
    } else {
237
      fprintf(stderr, "Missing dimensions.\n");
238 239 240 241 242
      PrintHelp(argv[0]);
    }
  }
}

Frank Barchard's avatar
Frank Barchard committed
243 244
bool UpdateMetrics(uint8_t* ch_org,
                   uint8_t* ch_rec,
Frank Barchard's avatar
Frank Barchard committed
245 246 247
                   const int y_size,
                   const int uv_size,
                   const size_t total_size,
248 249
                   int number_of_frames,
                   metric* cur_distortion_psnr,
Frank Barchard's avatar
Frank Barchard committed
250 251
                   metric* distorted_frame,
                   bool do_psnr) {
252
  const int uv_offset = (do_swap_uv ? uv_size : 0);
Frank Barchard's avatar
Frank Barchard committed
253 254 255 256
  const uint8_t* const u_org = ch_org + y_size + uv_offset;
  const uint8_t* const u_rec = ch_rec + y_size;
  const uint8_t* const v_org = ch_org + y_size + (uv_size - uv_offset);
  const uint8_t* const v_rec = ch_rec + y_size + uv_size;
257
  if (do_psnr) {
258
#ifdef HAVE_JPEG
259
    double y_err = static_cast<double>(
Frank Barchard's avatar
Frank Barchard committed
260
        libyuv::ComputeSumSquareError(ch_org, ch_rec, y_size));
261
    double u_err = static_cast<double>(
Frank Barchard's avatar
Frank Barchard committed
262
        libyuv::ComputeSumSquareError(u_org, u_rec, uv_size));
263
    double v_err = static_cast<double>(
Frank Barchard's avatar
Frank Barchard committed
264
        libyuv::ComputeSumSquareError(v_org, v_rec, uv_size));
265
#else
266 267 268
    double y_err = ComputeSumSquareError(ch_org, ch_rec, y_size);
    double u_err = ComputeSumSquareError(u_org, u_rec, uv_size);
    double v_err = ComputeSumSquareError(v_org, v_rec, uv_size);
269
#endif
270 271 272 273 274 275 276 277
    const double total_err = y_err + u_err + v_err;
    cur_distortion_psnr->global_y += y_err;
    cur_distortion_psnr->global_u += u_err;
    cur_distortion_psnr->global_v += v_err;
    cur_distortion_psnr->global_all += total_err;
    distorted_frame->y = ComputePSNR(y_err, static_cast<double>(y_size));
    distorted_frame->u = ComputePSNR(u_err, static_cast<double>(uv_size));
    distorted_frame->v = ComputePSNR(v_err, static_cast<double>(uv_size));
Frank Barchard's avatar
Frank Barchard committed
278 279
    distorted_frame->all =
        ComputePSNR(total_err, static_cast<double>(total_size));
280 281
  } else {
    distorted_frame->y = CalcSSIM(ch_org, ch_rec, image_width, image_height);
Frank Barchard's avatar
Frank Barchard committed
282 283 284 285
    distorted_frame->u =
        CalcSSIM(u_org, u_rec, (image_width + 1) / 2, (image_height + 1) / 2);
    distorted_frame->v =
        CalcSSIM(v_org, v_rec, (image_width + 1) / 2, (image_height + 1) / 2);
286
    distorted_frame->all =
Frank Barchard's avatar
Frank Barchard committed
287 288
        (distorted_frame->y + distorted_frame->u + distorted_frame->v) /
        total_size;
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
    distorted_frame->y /= y_size;
    distorted_frame->u /= uv_size;
    distorted_frame->v /= uv_size;

    if (do_lssim) {
      distorted_frame->all = CalcLSSIM(distorted_frame->all);
      distorted_frame->y = CalcLSSIM(distorted_frame->y);
      distorted_frame->u = CalcLSSIM(distorted_frame->u);
      distorted_frame->v = CalcLSSIM(distorted_frame->v);
    }
  }

  cur_distortion_psnr->y += distorted_frame->y;
  cur_distortion_psnr->u += distorted_frame->u;
  cur_distortion_psnr->v += distorted_frame->v;
  cur_distortion_psnr->all += distorted_frame->all;

  bool ismin = false;
307
  if (distorted_frame->y < cur_distortion_psnr->min_y) {
308
    cur_distortion_psnr->min_y = distorted_frame->y;
309 310
  }
  if (distorted_frame->u < cur_distortion_psnr->min_u) {
311
    cur_distortion_psnr->min_u = distorted_frame->u;
312 313
  }
  if (distorted_frame->v < cur_distortion_psnr->min_v) {
314
    cur_distortion_psnr->min_v = distorted_frame->v;
315
  }
316 317 318 319 320 321 322 323
  if (distorted_frame->all < cur_distortion_psnr->min_all) {
    cur_distortion_psnr->min_all = distorted_frame->all;
    cur_distortion_psnr->min_frame = number_of_frames;
    ismin = true;
  }
  return ismin;
}

324
int main(int argc, const char* argv[]) {
325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
  ParseOptions(argc, argv);
  if (!do_psnr && !do_ssim) {
    do_psnr = true;
  }

#ifdef _OPENMP
  if (num_threads) {
    omp_set_num_threads(num_threads);
  }
  if (verbose) {
    printf("OpenMP %d procs\n", omp_get_num_procs());
  }
#endif
  // Open original file (first file argument)
  FILE* const file_org = fopen(argv[fileindex_org], "rb");
  if (file_org == NULL) {
    fprintf(stderr, "Cannot open %s\n", argv[fileindex_org]);
    exit(1);
  }

  // Open all files to compare to
Frank Barchard's avatar
Frank Barchard committed
346 347
  FILE** file_rec = new FILE*[num_rec];
  memset(file_rec, 0, num_rec * sizeof(FILE*));  // NOLINT
348
  for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) {
349
    file_rec[cur_rec] = fopen(argv[fileindex_rec + cur_rec], "rb");
350
    if (file_rec[cur_rec] == NULL) {
351
      fprintf(stderr, "Cannot open %s\n", argv[fileindex_rec + cur_rec]);
352 353 354 355 356 357 358 359 360 361
      fclose(file_org);
      for (int i = 0; i < cur_rec; ++i) {
        fclose(file_rec[i]);
      }
      delete[] file_rec;
      exit(1);
    }
  }

  const int y_size = image_width * image_height;
362
  const int uv_size = ((image_width + 1) / 2) * ((image_height + 1) / 2);
Frank Barchard's avatar
Frank Barchard committed
363
  const size_t total_size = y_size + 2 * uv_size;  // NOLINT
364
#if defined(_MSC_VER)
365 366 367 368
  _fseeki64(
      file_org,
      static_cast<__int64>(num_skip_org) * static_cast<__int64>(total_size),
      SEEK_SET);
369 370 371 372 373
#else
  fseek(file_org, num_skip_org * total_size, SEEK_SET);
#endif
  for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) {
#if defined(_MSC_VER)
374 375 376 377
    _fseeki64(
        file_rec[cur_rec],
        static_cast<__int64>(num_skip_rec) * static_cast<__int64>(total_size),
        SEEK_SET);
378 379 380 381 382
#else
    fseek(file_rec[cur_rec], num_skip_rec * total_size, SEEK_SET);
#endif
  }

Frank Barchard's avatar
Frank Barchard committed
383 384
  uint8_t* const ch_org = new uint8_t[total_size];
  uint8_t* const ch_rec = new uint8_t[total_size];
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
  if (ch_org == NULL || ch_rec == NULL) {
    fprintf(stderr, "No memory available\n");
    fclose(file_org);
    for (int i = 0; i < num_rec; ++i) {
      fclose(file_rec[i]);
    }
    delete[] ch_org;
    delete[] ch_rec;
    delete[] file_rec;
    exit(1);
  }

  metric* const distortion_psnr = new metric[num_rec];
  metric* const distortion_ssim = new metric[num_rec];
  for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) {
    metric* cur_distortion_psnr = &distortion_psnr[cur_rec];
    cur_distortion_psnr->y = 0.0;
    cur_distortion_psnr->u = 0.0;
    cur_distortion_psnr->v = 0.0;
    cur_distortion_psnr->all = 0.0;
    cur_distortion_psnr->min_y = kMaxPSNR;
    cur_distortion_psnr->min_u = kMaxPSNR;
    cur_distortion_psnr->min_v = kMaxPSNR;
    cur_distortion_psnr->min_all = kMaxPSNR;
    cur_distortion_psnr->min_frame = 0;
    cur_distortion_psnr->global_y = 0.0;
    cur_distortion_psnr->global_u = 0.0;
    cur_distortion_psnr->global_v = 0.0;
    cur_distortion_psnr->global_all = 0.0;
    distortion_ssim[cur_rec] = cur_distortion_psnr[cur_rec];
  }

  if (verbose) {
    printf("Size: %dx%d\n", image_width, image_height);
  }

  if (!quiet) {
    printf("Frame");
    if (do_psnr) {
      printf("\t PSNR-Y \t PSNR-U \t PSNR-V \t PSNR-All \t Frame");
    }
    if (do_ssim) {
      printf("\t  SSIM-Y\t  SSIM-U\t  SSIM-V\t  SSIM-All\t Frame");
    }
    if (show_name) {
      printf("\tName\n");
    } else {
      printf("\n");
    }
  }

  int number_of_frames;
Frank Barchard's avatar
Frank Barchard committed
437
  for (number_of_frames = 0;; ++number_of_frames) {
438
    if (num_frames && number_of_frames >= num_frames) {
439
      break;
440
    }
441

Frank Barchard's avatar
Frank Barchard committed
442
    size_t bytes_org = fread(ch_org, sizeof(uint8_t), total_size, file_org);
443 444 445
    if (bytes_org < total_size) {
#ifdef HAVE_JPEG
      // Try parsing file as a jpeg.
Frank Barchard's avatar
Frank Barchard committed
446
      uint8_t* const ch_jpeg = new uint8_t[bytes_org];
447
      memcpy(ch_jpeg, ch_org, bytes_org);
448
      memset(ch_org, 0, total_size);
449

Frank Barchard's avatar
Frank Barchard committed
450 451
      if (0 != libyuv::MJPGToI420(ch_jpeg, bytes_org, ch_org, image_width,
                                  ch_org + y_size, (image_width + 1) / 2,
452
                                  ch_org + y_size + uv_size,
Frank Barchard's avatar
Frank Barchard committed
453 454
                                  (image_width + 1) / 2, image_width,
                                  image_height, image_width, image_height)) {
455 456 457 458 459
        delete[] ch_jpeg;
        break;
      }
      delete[] ch_jpeg;
#else
460
      break;
461 462
#endif  // HAVE_JPEG
    }
463 464

    for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) {
Frank Barchard's avatar
Frank Barchard committed
465
      size_t bytes_rec =
Frank Barchard's avatar
Frank Barchard committed
466
          fread(ch_rec, sizeof(uint8_t), total_size, file_rec[cur_rec]);
467 468 469
      if (bytes_rec < total_size) {
#ifdef HAVE_JPEG
        // Try parsing file as a jpeg.
Frank Barchard's avatar
Frank Barchard committed
470
        uint8_t* const ch_jpeg = new uint8_t[bytes_rec];
471
        memcpy(ch_jpeg, ch_rec, bytes_rec);
472
        memset(ch_rec, 0, total_size);
473

Frank Barchard's avatar
Frank Barchard committed
474 475
        if (0 != libyuv::MJPGToI420(ch_jpeg, bytes_rec, ch_rec, image_width,
                                    ch_rec + y_size, (image_width + 1) / 2,
476
                                    ch_rec + y_size + uv_size,
Frank Barchard's avatar
Frank Barchard committed
477 478
                                    (image_width + 1) / 2, image_width,
                                    image_height, image_width, image_height)) {
479 480 481 482 483
          delete[] ch_jpeg;
          break;
        }
        delete[] ch_jpeg;
#else
484
        break;
485 486
#endif  // HAVE_JPEG
      }
487 488 489 490 491

      if (verbose) {
        printf("%5d", number_of_frames);
      }
      if (do_psnr) {
492
        metric distorted_frame = {};
493
        metric* cur_distortion_psnr = &distortion_psnr[cur_rec];
Frank Barchard's avatar
Frank Barchard committed
494 495
        bool ismin = UpdateMetrics(ch_org, ch_rec, y_size, uv_size, total_size,
                                   number_of_frames, cur_distortion_psnr,
496 497 498 499 500 501 502 503 504 505
                                   &distorted_frame, true);
        if (verbose) {
          printf("\t%10.6f", distorted_frame.y);
          printf("\t%10.6f", distorted_frame.u);
          printf("\t%10.6f", distorted_frame.v);
          printf("\t%10.6f", distorted_frame.all);
          printf("\t%5s", ismin ? "min" : "");
        }
      }
      if (do_ssim) {
506
        metric distorted_frame = {};
507
        metric* cur_distortion_ssim = &distortion_ssim[cur_rec];
Frank Barchard's avatar
Frank Barchard committed
508 509
        bool ismin = UpdateMetrics(ch_org, ch_rec, y_size, uv_size, total_size,
                                   number_of_frames, cur_distortion_ssim,
510 511 512 513 514 515 516 517 518 519 520
                                   &distorted_frame, false);
        if (verbose) {
          printf("\t%10.6f", distorted_frame.y);
          printf("\t%10.6f", distorted_frame.u);
          printf("\t%10.6f", distorted_frame.v);
          printf("\t%10.6f", distorted_frame.all);
          printf("\t%5s", ismin ? "min" : "");
        }
      }
      if (verbose) {
        if (show_name) {
521
          printf("\t%s", argv[fileindex_rec + cur_rec]);
522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544
        }
        printf("\n");
      }
    }
  }

  // Final PSNR computation.
  for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) {
    metric* cur_distortion_psnr = &distortion_psnr[cur_rec];
    metric* cur_distortion_ssim = &distortion_ssim[cur_rec];
    if (number_of_frames > 0) {
      const double norm = 1. / static_cast<double>(number_of_frames);
      cur_distortion_psnr->y *= norm;
      cur_distortion_psnr->u *= norm;
      cur_distortion_psnr->v *= norm;
      cur_distortion_psnr->all *= norm;
      cur_distortion_ssim->y *= norm;
      cur_distortion_ssim->u *= norm;
      cur_distortion_ssim->v *= norm;
      cur_distortion_ssim->all *= norm;
    }

    if (do_psnr) {
Frank Barchard's avatar
Frank Barchard committed
545 546 547 548 549 550 551 552 553 554 555 556 557 558
      const double global_psnr_y =
          ComputePSNR(cur_distortion_psnr->global_y,
                      static_cast<double>(y_size) * number_of_frames);
      const double global_psnr_u =
          ComputePSNR(cur_distortion_psnr->global_u,
                      static_cast<double>(uv_size) * number_of_frames);
      const double global_psnr_v =
          ComputePSNR(cur_distortion_psnr->global_v,
                      static_cast<double>(uv_size) * number_of_frames);
      const double global_psnr_all =
          ComputePSNR(cur_distortion_psnr->global_all,
                      static_cast<double>(total_size) * number_of_frames);
      printf("Global:\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d", global_psnr_y,
             global_psnr_u, global_psnr_v, global_psnr_all, number_of_frames);
559
      if (show_name) {
560
        printf("\t%s", argv[fileindex_rec + cur_rec]);
561 562 563 564 565 566 567
      }
      printf("\n");
    }

    if (!quiet) {
      printf("Avg:");
      if (do_psnr) {
Frank Barchard's avatar
Frank Barchard committed
568 569 570
        printf("\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d", cur_distortion_psnr->y,
               cur_distortion_psnr->u, cur_distortion_psnr->v,
               cur_distortion_psnr->all, number_of_frames);
571 572
      }
      if (do_ssim) {
Frank Barchard's avatar
Frank Barchard committed
573 574 575
        printf("\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d", cur_distortion_ssim->y,
               cur_distortion_ssim->u, cur_distortion_ssim->v,
               cur_distortion_ssim->all, number_of_frames);
576 577
      }
      if (show_name) {
578
        printf("\t%s", argv[fileindex_rec + cur_rec]);
579 580 581 582 583 584 585
      }
      printf("\n");
    }
    if (!quiet) {
      printf("Min:");
      if (do_psnr) {
        printf("\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d",
Frank Barchard's avatar
Frank Barchard committed
586 587 588
               cur_distortion_psnr->min_y, cur_distortion_psnr->min_u,
               cur_distortion_psnr->min_v, cur_distortion_psnr->min_all,
               cur_distortion_psnr->min_frame);
589 590 591
      }
      if (do_ssim) {
        printf("\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d",
Frank Barchard's avatar
Frank Barchard committed
592 593 594
               cur_distortion_ssim->min_y, cur_distortion_ssim->min_u,
               cur_distortion_ssim->min_v, cur_distortion_ssim->min_all,
               cur_distortion_ssim->min_frame);
595 596
      }
      if (show_name) {
597
        printf("\t%s", argv[fileindex_rec + cur_rec]);
598 599 600 601 602
      }
      printf("\n");
    }

    if (do_mse) {
Frank Barchard's avatar
Frank Barchard committed
603 604 605 606 607 608 609 610 611 612 613 614 615 616
      double global_mse_y =
          GetMSE(cur_distortion_psnr->global_y,
                 static_cast<double>(y_size) * number_of_frames);
      double global_mse_u =
          GetMSE(cur_distortion_psnr->global_u,
                 static_cast<double>(uv_size) * number_of_frames);
      double global_mse_v =
          GetMSE(cur_distortion_psnr->global_v,
                 static_cast<double>(uv_size) * number_of_frames);
      double global_mse_all =
          GetMSE(cur_distortion_psnr->global_all,
                 static_cast<double>(total_size) * number_of_frames);
      printf("MSE:\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d", global_mse_y,
             global_mse_u, global_mse_v, global_mse_all, number_of_frames);
617
      if (show_name) {
618
        printf("\t%s", argv[fileindex_rec + cur_rec]);
619 620 621 622 623 624 625 626 627 628 629 630 631 632 633
      }
      printf("\n");
    }
  }
  fclose(file_org);
  for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) {
    fclose(file_rec[cur_rec]);
  }
  delete[] distortion_psnr;
  delete[] distortion_ssim;
  delete[] ch_org;
  delete[] ch_rec;
  delete[] file_rec;
  return 0;
}