michael@0: /* michael@0: * Copyright 2013 The LibYuv Project Authors. All rights reserved. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license michael@0: * that can be found in the LICENSE file in the root of the source michael@0: * tree. An additional intellectual property rights grant can be found michael@0: * in the file PATENTS. All contributing project authors may michael@0: * be found in the AUTHORS file in the root of the source tree. michael@0: */ michael@0: michael@0: // Get PSNR or SSIM for video sequence. Assuming RAW 4:2:0 Y:Cb:Cr format michael@0: // To build: g++ -O3 -o psnr psnr.cc ssim.cc psnr_main.cc michael@0: // or VisualC: cl /Ox psnr.cc ssim.cc psnr_main.cc michael@0: // michael@0: // To enable OpenMP and SSE2 michael@0: // gcc: g++ -msse2 -O3 -fopenmp -o psnr psnr.cc ssim.cc psnr_main.cc michael@0: // vc: cl /arch:SSE2 /Ox /openmp psnr.cc ssim.cc psnr_main.cc michael@0: // michael@0: // Usage: psnr org_seq rec_seq -s width height [-skip skip_org skip_rec] michael@0: michael@0: #ifndef _CRT_SECURE_NO_WARNINGS michael@0: #define _CRT_SECURE_NO_WARNINGS michael@0: #endif michael@0: michael@0: #include michael@0: #include michael@0: #include michael@0: #include michael@0: #ifdef _OPENMP michael@0: #include michael@0: #endif michael@0: michael@0: #include "./psnr.h" michael@0: #include "./ssim.h" michael@0: michael@0: struct metric { michael@0: double y, u, v, all; michael@0: double min_y, min_u, min_v, min_all; michael@0: double global_y, global_u, global_v, global_all; michael@0: int min_frame; michael@0: }; michael@0: michael@0: // options michael@0: bool verbose = false; michael@0: bool quiet = false; michael@0: bool show_name = false; michael@0: bool do_swap_uv = false; michael@0: bool do_psnr = false; michael@0: bool do_ssim = false; michael@0: bool do_mse = false; michael@0: bool do_lssim = false; michael@0: int image_width = 0, image_height = 0; michael@0: int fileindex_org = 0; // argv argument contains the source file name. michael@0: int fileindex_rec = 0; // argv argument contains the destination file name. michael@0: int num_rec = 0; michael@0: int num_skip_org = 0; michael@0: int num_skip_rec = 0; michael@0: int num_frames = 0; michael@0: #ifdef _OPENMP michael@0: int num_threads = 0; michael@0: #endif michael@0: michael@0: // Parse PYUV format. ie name.1920x800_24Hz_P420.yuv michael@0: bool ExtractResolutionFromFilename(const char* name, michael@0: int* width_ptr, michael@0: int* height_ptr) { michael@0: // Isolate the .width_height. section of the filename by searching for a michael@0: // dot or underscore followed by a digit. michael@0: for (int i = 0; name[i]; ++i) { michael@0: if ((name[i] == '.' || name[i] == '_') && michael@0: name[i + 1] >= '0' && name[i + 1] <= '9') { michael@0: int n = sscanf(name + i + 1, "%dx%d", width_ptr, height_ptr); // NOLINT michael@0: if (2 == n) { michael@0: return true; michael@0: } michael@0: } michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: // Scale Y channel from 16..240 to 0..255. michael@0: // This can be useful when comparing codecs that are inconsistant about Y michael@0: uint8 ScaleY(uint8 y) { michael@0: int ny = (y - 16) * 256 / 224; michael@0: if (ny < 0) ny = 0; michael@0: if (ny > 255) ny = 255; michael@0: return static_cast(ny); michael@0: } michael@0: michael@0: // MSE = Mean Square Error michael@0: double GetMSE(double sse, double size) { michael@0: return sse / size; michael@0: } michael@0: michael@0: void PrintHelp(const char * program) { michael@0: printf("%s [-options] org_seq rec_seq [rec_seq2.. etc]\n", program); michael@0: printf("options:\n"); michael@0: printf(" -s .... specify YUV size, mandatory if none of the " michael@0: "sequences have the\n"); michael@0: printf(" resolution embedded in their filename (ie. " michael@0: "name.1920x800_24Hz_P420.yuv)\n"); michael@0: printf(" -psnr .................. compute PSNR (default)\n"); michael@0: printf(" -ssim .................. compute SSIM\n"); michael@0: printf(" -mse ................... compute MSE\n"); michael@0: printf(" -swap .................. Swap U and V plane\n"); michael@0: printf(" -skip ...... Number of frame to skip of org and rec\n"); michael@0: printf(" -frames .......... Number of frames to compare\n"); michael@0: #ifdef _OPENMP michael@0: printf(" -t ............... Number of threads\n"); michael@0: #endif michael@0: printf(" -n ..................... Show file name\n"); michael@0: printf(" -v ..................... verbose++\n"); michael@0: printf(" -q ..................... quiet\n"); michael@0: printf(" -h ..................... this help\n"); michael@0: exit(0); michael@0: } michael@0: michael@0: void ParseOptions(int argc, const char* argv[]) { michael@0: if (argc <= 1) PrintHelp(argv[0]); michael@0: for (int c = 1; c < argc; ++c) { michael@0: if (!strcmp(argv[c], "-v")) { michael@0: verbose = true; michael@0: } else if (!strcmp(argv[c], "-q")) { michael@0: quiet = true; michael@0: } else if (!strcmp(argv[c], "-n")) { michael@0: show_name = true; michael@0: } else if (!strcmp(argv[c], "-psnr")) { michael@0: do_psnr = true; michael@0: } else if (!strcmp(argv[c], "-mse")) { michael@0: do_mse = true; michael@0: } else if (!strcmp(argv[c], "-ssim")) { michael@0: do_ssim = true; michael@0: } else if (!strcmp(argv[c], "-lssim")) { michael@0: do_ssim = true; michael@0: do_lssim = true; michael@0: } else if (!strcmp(argv[c], "-swap")) { michael@0: do_swap_uv = true; michael@0: } else if (!strcmp(argv[c], "-h") || !strcmp(argv[c], "-help")) { michael@0: PrintHelp(argv[0]); michael@0: } else if (!strcmp(argv[c], "-s") && c + 2 < argc) { michael@0: image_width = atoi(argv[++c]); // NOLINT michael@0: image_height = atoi(argv[++c]); // NOLINT michael@0: } else if (!strcmp(argv[c], "-skip") && c + 2 < argc) { michael@0: num_skip_org = atoi(argv[++c]); // NOLINT michael@0: num_skip_rec = atoi(argv[++c]); // NOLINT michael@0: } else if (!strcmp(argv[c], "-frames") && c + 1 < argc) { michael@0: num_frames = atoi(argv[++c]); // NOLINT michael@0: #ifdef _OPENMP michael@0: } else if (!strcmp(argv[c], "-t") && c + 1 < argc) { michael@0: num_threads = atoi(argv[++c]); // NOLINT michael@0: #endif michael@0: } else if (argv[c][0] == '-') { michael@0: fprintf(stderr, "Unknown option. %s\n", argv[c]); michael@0: } else if (fileindex_org == 0) { michael@0: fileindex_org = c; michael@0: } else if (fileindex_rec == 0) { michael@0: fileindex_rec = c; michael@0: num_rec = 1; michael@0: } else { michael@0: ++num_rec; michael@0: } michael@0: } michael@0: if (fileindex_org == 0 || fileindex_rec == 0) { michael@0: fprintf(stderr, "Missing filenames\n"); michael@0: PrintHelp(argv[0]); michael@0: } michael@0: if (num_skip_org < 0 || num_skip_rec < 0) { michael@0: fprintf(stderr, "Skipped frames incorrect\n"); michael@0: PrintHelp(argv[0]); michael@0: } michael@0: if (num_frames < 0) { michael@0: fprintf(stderr, "Number of frames incorrect\n"); michael@0: PrintHelp(argv[0]); michael@0: } michael@0: if (image_width == 0 || image_height == 0) { michael@0: int org_width, org_height; michael@0: int rec_width, rec_height; michael@0: bool org_res_avail = ExtractResolutionFromFilename(argv[fileindex_org], michael@0: &org_width, michael@0: &org_height); michael@0: bool rec_res_avail = ExtractResolutionFromFilename(argv[fileindex_rec], michael@0: &rec_width, michael@0: &rec_height); michael@0: if (org_res_avail) { michael@0: if (rec_res_avail) { michael@0: if ((org_width == rec_width) && (org_height == rec_height)) { michael@0: image_width = org_width; michael@0: image_height = org_height; michael@0: } else { michael@0: fprintf(stderr, "Sequences have different resolutions.\n"); michael@0: PrintHelp(argv[0]); michael@0: } michael@0: } else { michael@0: image_width = org_width; michael@0: image_height = org_height; michael@0: } michael@0: } else if (rec_res_avail) { michael@0: image_width = rec_width; michael@0: image_height = rec_height; michael@0: } else { michael@0: fprintf(stderr, "Missing dimensions.\n"); michael@0: PrintHelp(argv[0]); michael@0: } michael@0: } michael@0: } michael@0: michael@0: bool UpdateMetrics(uint8* ch_org, uint8* ch_rec, michael@0: const int y_size, const int uv_size, const size_t total_size, michael@0: int number_of_frames, michael@0: metric* cur_distortion_psnr, michael@0: metric* distorted_frame, bool do_psnr) { michael@0: const int uv_offset = (do_swap_uv ? uv_size : 0); michael@0: const uint8* const u_org = ch_org + y_size + uv_offset; michael@0: const uint8* const u_rec = ch_rec + y_size; michael@0: const uint8* const v_org = ch_org + y_size + (uv_size - uv_offset); michael@0: const uint8* const v_rec = ch_rec + y_size + uv_size; michael@0: if (do_psnr) { michael@0: double y_err = ComputeSumSquareError(ch_org, ch_rec, y_size); michael@0: double u_err = ComputeSumSquareError(u_org, u_rec, uv_size); michael@0: double v_err = ComputeSumSquareError(v_org, v_rec, uv_size); michael@0: const double total_err = y_err + u_err + v_err; michael@0: cur_distortion_psnr->global_y += y_err; michael@0: cur_distortion_psnr->global_u += u_err; michael@0: cur_distortion_psnr->global_v += v_err; michael@0: cur_distortion_psnr->global_all += total_err; michael@0: distorted_frame->y = ComputePSNR(y_err, static_cast(y_size)); michael@0: distorted_frame->u = ComputePSNR(u_err, static_cast(uv_size)); michael@0: distorted_frame->v = ComputePSNR(v_err, static_cast(uv_size)); michael@0: distorted_frame->all = ComputePSNR(total_err, michael@0: static_cast(total_size)); michael@0: } else { michael@0: distorted_frame->y = CalcSSIM(ch_org, ch_rec, image_width, image_height); michael@0: distorted_frame->u = CalcSSIM(u_org, u_rec, image_width / 2, michael@0: image_height / 2); michael@0: distorted_frame->v = CalcSSIM(v_org, v_rec, image_width / 2, michael@0: image_height / 2); michael@0: distorted_frame->all = michael@0: (distorted_frame->y + distorted_frame->u + distorted_frame->v) michael@0: / total_size; michael@0: distorted_frame->y /= y_size; michael@0: distorted_frame->u /= uv_size; michael@0: distorted_frame->v /= uv_size; michael@0: michael@0: if (do_lssim) { michael@0: distorted_frame->all = CalcLSSIM(distorted_frame->all); michael@0: distorted_frame->y = CalcLSSIM(distorted_frame->y); michael@0: distorted_frame->u = CalcLSSIM(distorted_frame->u); michael@0: distorted_frame->v = CalcLSSIM(distorted_frame->v); michael@0: } michael@0: } michael@0: michael@0: cur_distortion_psnr->y += distorted_frame->y; michael@0: cur_distortion_psnr->u += distorted_frame->u; michael@0: cur_distortion_psnr->v += distorted_frame->v; michael@0: cur_distortion_psnr->all += distorted_frame->all; michael@0: michael@0: bool ismin = false; michael@0: if (distorted_frame->y < cur_distortion_psnr->min_y) michael@0: cur_distortion_psnr->min_y = distorted_frame->y; michael@0: if (distorted_frame->u < cur_distortion_psnr->min_u) michael@0: cur_distortion_psnr->min_u = distorted_frame->u; michael@0: if (distorted_frame->v < cur_distortion_psnr->min_v) michael@0: cur_distortion_psnr->min_v = distorted_frame->v; michael@0: if (distorted_frame->all < cur_distortion_psnr->min_all) { michael@0: cur_distortion_psnr->min_all = distorted_frame->all; michael@0: cur_distortion_psnr->min_frame = number_of_frames; michael@0: ismin = true; michael@0: } michael@0: return ismin; michael@0: } michael@0: michael@0: int main(int argc, const char* argv[]) { michael@0: ParseOptions(argc, argv); michael@0: if (!do_psnr && !do_ssim) { michael@0: do_psnr = true; michael@0: } michael@0: michael@0: #ifdef _OPENMP michael@0: if (num_threads) { michael@0: omp_set_num_threads(num_threads); michael@0: } michael@0: if (verbose) { michael@0: printf("OpenMP %d procs\n", omp_get_num_procs()); michael@0: } michael@0: #endif michael@0: // Open original file (first file argument) michael@0: FILE* const file_org = fopen(argv[fileindex_org], "rb"); michael@0: if (file_org == NULL) { michael@0: fprintf(stderr, "Cannot open %s\n", argv[fileindex_org]); michael@0: exit(1); michael@0: } michael@0: michael@0: // Open all files to compare to michael@0: FILE** file_rec = new FILE* [num_rec]; michael@0: memset(file_rec, 0, num_rec * sizeof(FILE*)); // NOLINT michael@0: for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) { michael@0: file_rec[cur_rec] = fopen(argv[fileindex_rec + cur_rec], "rb"); michael@0: if (file_rec[cur_rec] == NULL) { michael@0: fprintf(stderr, "Cannot open %s\n", argv[fileindex_rec + cur_rec]); michael@0: fclose(file_org); michael@0: for (int i = 0; i < cur_rec; ++i) { michael@0: fclose(file_rec[i]); michael@0: } michael@0: delete[] file_rec; michael@0: exit(1); michael@0: } michael@0: } michael@0: michael@0: const int y_size = image_width * image_height; michael@0: const int uv_size = ((image_width + 1) / 2) * ((image_height + 1) / 2); michael@0: const size_t total_size = y_size + 2 * uv_size; // NOLINT michael@0: #if defined(_MSC_VER) michael@0: _fseeki64(file_org, michael@0: static_cast<__int64>(num_skip_org) * michael@0: static_cast<__int64>(total_size), SEEK_SET); michael@0: #else michael@0: fseek(file_org, num_skip_org * total_size, SEEK_SET); michael@0: #endif michael@0: for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) { michael@0: #if defined(_MSC_VER) michael@0: _fseeki64(file_rec[cur_rec], michael@0: static_cast<__int64>(num_skip_rec) * michael@0: static_cast<__int64>(total_size), michael@0: SEEK_SET); michael@0: #else michael@0: fseek(file_rec[cur_rec], num_skip_rec * total_size, SEEK_SET); michael@0: #endif michael@0: } michael@0: michael@0: uint8* const ch_org = new uint8[total_size]; michael@0: uint8* const ch_rec = new uint8[total_size]; michael@0: if (ch_org == NULL || ch_rec == NULL) { michael@0: fprintf(stderr, "No memory available\n"); michael@0: fclose(file_org); michael@0: for (int i = 0; i < num_rec; ++i) { michael@0: fclose(file_rec[i]); michael@0: } michael@0: delete[] ch_org; michael@0: delete[] ch_rec; michael@0: delete[] file_rec; michael@0: exit(1); michael@0: } michael@0: michael@0: metric* const distortion_psnr = new metric[num_rec]; michael@0: metric* const distortion_ssim = new metric[num_rec]; michael@0: for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) { michael@0: metric* cur_distortion_psnr = &distortion_psnr[cur_rec]; michael@0: cur_distortion_psnr->y = 0.0; michael@0: cur_distortion_psnr->u = 0.0; michael@0: cur_distortion_psnr->v = 0.0; michael@0: cur_distortion_psnr->all = 0.0; michael@0: cur_distortion_psnr->min_y = kMaxPSNR; michael@0: cur_distortion_psnr->min_u = kMaxPSNR; michael@0: cur_distortion_psnr->min_v = kMaxPSNR; michael@0: cur_distortion_psnr->min_all = kMaxPSNR; michael@0: cur_distortion_psnr->min_frame = 0; michael@0: cur_distortion_psnr->global_y = 0.0; michael@0: cur_distortion_psnr->global_u = 0.0; michael@0: cur_distortion_psnr->global_v = 0.0; michael@0: cur_distortion_psnr->global_all = 0.0; michael@0: distortion_ssim[cur_rec] = cur_distortion_psnr[cur_rec]; michael@0: } michael@0: michael@0: if (verbose) { michael@0: printf("Size: %dx%d\n", image_width, image_height); michael@0: } michael@0: michael@0: if (!quiet) { michael@0: printf("Frame"); michael@0: if (do_psnr) { michael@0: printf("\t PSNR-Y \t PSNR-U \t PSNR-V \t PSNR-All \t Frame"); michael@0: } michael@0: if (do_ssim) { michael@0: printf("\t SSIM-Y\t SSIM-U\t SSIM-V\t SSIM-All\t Frame"); michael@0: } michael@0: if (show_name) { michael@0: printf("\tName\n"); michael@0: } else { michael@0: printf("\n"); michael@0: } michael@0: } michael@0: michael@0: int number_of_frames; michael@0: for (number_of_frames = 0; ; ++number_of_frames) { michael@0: if (num_frames && number_of_frames >= num_frames) michael@0: break; michael@0: michael@0: size_t bytes_org = fread(ch_org, sizeof(uint8), total_size, file_org); michael@0: if (bytes_org < total_size) michael@0: break; michael@0: michael@0: for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) { michael@0: size_t bytes_rec = fread(ch_rec, sizeof(uint8), michael@0: total_size, file_rec[cur_rec]); michael@0: if (bytes_rec < total_size) michael@0: break; michael@0: michael@0: if (verbose) { michael@0: printf("%5d", number_of_frames); michael@0: } michael@0: if (do_psnr) { michael@0: metric distorted_frame; michael@0: metric* cur_distortion_psnr = &distortion_psnr[cur_rec]; michael@0: bool ismin = UpdateMetrics(ch_org, ch_rec, michael@0: y_size, uv_size, total_size, michael@0: number_of_frames, michael@0: cur_distortion_psnr, michael@0: &distorted_frame, true); michael@0: if (verbose) { michael@0: printf("\t%10.6f", distorted_frame.y); michael@0: printf("\t%10.6f", distorted_frame.u); michael@0: printf("\t%10.6f", distorted_frame.v); michael@0: printf("\t%10.6f", distorted_frame.all); michael@0: printf("\t%5s", ismin ? "min" : ""); michael@0: } michael@0: } michael@0: if (do_ssim) { michael@0: metric distorted_frame; michael@0: metric* cur_distortion_ssim = &distortion_ssim[cur_rec]; michael@0: bool ismin = UpdateMetrics(ch_org, ch_rec, michael@0: y_size, uv_size, total_size, michael@0: number_of_frames, michael@0: cur_distortion_ssim, michael@0: &distorted_frame, false); michael@0: if (verbose) { michael@0: printf("\t%10.6f", distorted_frame.y); michael@0: printf("\t%10.6f", distorted_frame.u); michael@0: printf("\t%10.6f", distorted_frame.v); michael@0: printf("\t%10.6f", distorted_frame.all); michael@0: printf("\t%5s", ismin ? "min" : ""); michael@0: } michael@0: } michael@0: if (verbose) { michael@0: if (show_name) { michael@0: printf("\t%s", argv[fileindex_rec + cur_rec]); michael@0: } michael@0: printf("\n"); michael@0: } michael@0: } michael@0: } michael@0: michael@0: // Final PSNR computation. michael@0: for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) { michael@0: metric* cur_distortion_psnr = &distortion_psnr[cur_rec]; michael@0: metric* cur_distortion_ssim = &distortion_ssim[cur_rec]; michael@0: if (number_of_frames > 0) { michael@0: const double norm = 1. / static_cast(number_of_frames); michael@0: cur_distortion_psnr->y *= norm; michael@0: cur_distortion_psnr->u *= norm; michael@0: cur_distortion_psnr->v *= norm; michael@0: cur_distortion_psnr->all *= norm; michael@0: cur_distortion_ssim->y *= norm; michael@0: cur_distortion_ssim->u *= norm; michael@0: cur_distortion_ssim->v *= norm; michael@0: cur_distortion_ssim->all *= norm; michael@0: } michael@0: michael@0: if (do_psnr) { michael@0: const double global_psnr_y = ComputePSNR( michael@0: cur_distortion_psnr->global_y, michael@0: static_cast(y_size) * number_of_frames); michael@0: const double global_psnr_u = ComputePSNR( michael@0: cur_distortion_psnr->global_u, michael@0: static_cast(uv_size) * number_of_frames); michael@0: const double global_psnr_v = ComputePSNR( michael@0: cur_distortion_psnr->global_v, michael@0: static_cast(uv_size) * number_of_frames); michael@0: const double global_psnr_all = ComputePSNR( michael@0: cur_distortion_psnr->global_all, michael@0: static_cast(total_size) * number_of_frames); michael@0: printf("Global:\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d", michael@0: global_psnr_y, michael@0: global_psnr_u, michael@0: global_psnr_v, michael@0: global_psnr_all, michael@0: number_of_frames); michael@0: if (show_name) { michael@0: printf("\t%s", argv[fileindex_rec + cur_rec]); michael@0: } michael@0: printf("\n"); michael@0: } michael@0: michael@0: if (!quiet) { michael@0: printf("Avg:"); michael@0: if (do_psnr) { michael@0: printf("\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d", michael@0: cur_distortion_psnr->y, michael@0: cur_distortion_psnr->u, michael@0: cur_distortion_psnr->v, michael@0: cur_distortion_psnr->all, michael@0: number_of_frames); michael@0: } michael@0: if (do_ssim) { michael@0: printf("\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d", michael@0: cur_distortion_ssim->y, michael@0: cur_distortion_ssim->u, michael@0: cur_distortion_ssim->v, michael@0: cur_distortion_ssim->all, michael@0: number_of_frames); michael@0: } michael@0: if (show_name) { michael@0: printf("\t%s", argv[fileindex_rec + cur_rec]); michael@0: } michael@0: printf("\n"); michael@0: } michael@0: if (!quiet) { michael@0: printf("Min:"); michael@0: if (do_psnr) { michael@0: printf("\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d", michael@0: cur_distortion_psnr->min_y, michael@0: cur_distortion_psnr->min_u, michael@0: cur_distortion_psnr->min_v, michael@0: cur_distortion_psnr->min_all, michael@0: cur_distortion_psnr->min_frame); michael@0: } michael@0: if (do_ssim) { michael@0: printf("\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d", michael@0: cur_distortion_ssim->min_y, michael@0: cur_distortion_ssim->min_u, michael@0: cur_distortion_ssim->min_v, michael@0: cur_distortion_ssim->min_all, michael@0: cur_distortion_ssim->min_frame); michael@0: } michael@0: if (show_name) { michael@0: printf("\t%s", argv[fileindex_rec + cur_rec]); michael@0: } michael@0: printf("\n"); michael@0: } michael@0: michael@0: if (do_mse) { michael@0: double global_mse_y = GetMSE(cur_distortion_psnr->global_y, michael@0: static_cast(y_size) * number_of_frames); michael@0: double global_mse_u = GetMSE(cur_distortion_psnr->global_u, michael@0: static_cast(uv_size) * number_of_frames); michael@0: double global_mse_v = GetMSE(cur_distortion_psnr->global_v, michael@0: static_cast(uv_size) * number_of_frames); michael@0: double global_mse_all = GetMSE(cur_distortion_psnr->global_all, michael@0: static_cast(total_size) * number_of_frames); michael@0: printf("MSE:\t%10.6f\t%10.6f\t%10.6f\t%10.6f\t%5d", michael@0: global_mse_y, michael@0: global_mse_u, michael@0: global_mse_v, michael@0: global_mse_all, michael@0: number_of_frames); michael@0: if (show_name) { michael@0: printf("\t%s", argv[fileindex_rec + cur_rec]); michael@0: } michael@0: printf("\n"); michael@0: } michael@0: } michael@0: fclose(file_org); michael@0: for (int cur_rec = 0; cur_rec < num_rec; ++cur_rec) { michael@0: fclose(file_rec[cur_rec]); michael@0: } michael@0: delete[] distortion_psnr; michael@0: delete[] distortion_ssim; michael@0: delete[] ch_org; michael@0: delete[] ch_rec; michael@0: delete[] file_rec; michael@0: return 0; michael@0: }