psnr_main.cc 21 KB

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