psnr_main.cc 22 KB

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