blob: 0518ab84e0678cea05fe42b823a5627310a855be [file] [log] [blame]
Hangyu Kuangf047e7c2016-07-06 14:21:45 -07001/*
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
40struct 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
48bool verbose = false;
49bool quiet = false;
50bool show_name = false;
51bool do_swap_uv = false;
52bool do_psnr = false;
53bool do_ssim = false;
54bool do_mse = false;
55bool do_lssim = false;
56int image_width = 0, image_height = 0;
57int fileindex_org = 0; // argv argument contains the source file name.
58int fileindex_rec = 0; // argv argument contains the destination file name.
59int num_rec = 0;
60int num_skip_org = 0;
61int num_skip_rec = 0;
62int num_frames = 0;
63#ifdef _OPENMP
64int num_threads = 0;
65#endif
66
67// Parse PYUV format. ie name.1920x800_24Hz_P420.yuv
68bool 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
110uint8 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
118double GetMSE(double sse, double size) {
119 return sse / size;
120}
121
122void 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
148void 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
237bool 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
311int 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}