int ms_ssim(int (*read_frame)(float *ref_data, float *main_data, float *temp_data, int stride, void *user_data), void *user_data, int w, int h, const char *fmt) { double score = 0; double l_scores[SCALES], c_scores[SCALES], s_scores[SCALES]; float *ref_buf = 0; float *dis_buf = 0; float *temp_buf = 0; size_t data_sz; int stride; int ret = 1; if (w <= 0 || h <= 0 || (size_t)w > ALIGN_FLOOR(INT_MAX) / sizeof(float)) { goto fail_or_end; } stride = ALIGN_CEIL(w * sizeof(float)); if ((size_t)h > SIZE_MAX / stride) { goto fail_or_end; } data_sz = (size_t)stride * h; if (!(ref_buf = aligned_malloc(data_sz, MAX_ALIGN))) { printf("error: aligned_malloc failed for ref_buf.\n"); fflush(stdout); goto fail_or_end; } if (!(dis_buf = aligned_malloc(data_sz, MAX_ALIGN))) { printf("error: aligned_malloc failed for dis_buf.\n"); fflush(stdout); goto fail_or_end; } if (!(temp_buf = aligned_malloc(data_sz * 2, MAX_ALIGN))) { printf("error: aligned_malloc failed for temp_buf.\n"); fflush(stdout); goto fail_or_end; } int frm_idx = 0; while (1) { ret = read_frame(ref_buf, dis_buf, temp_buf, stride, user_data); if(ret == 1){ goto fail_or_end; } if (ret == 2) { break; } // compute ret = compute_ms_ssim(ref_buf, dis_buf, w, h, stride, stride, &score, l_scores, c_scores, s_scores); if (ret) { printf("error: compute_ms_ssim failed.\n"); fflush(stdout); goto fail_or_end; } // print printf("ms_ssim: %d %f\n", frm_idx, score); for (int scale=0; scale<SCALES; scale++) { printf("ms_ssim_l_scale%d: %d %f\n", scale, frm_idx, l_scores[scale]); printf("ms_ssim_c_scale%d: %d %f\n", scale, frm_idx, c_scores[scale]); printf("ms_ssim_s_scale%d: %d %f\n", scale, frm_idx, s_scores[scale]); } fflush(stdout); frm_idx++; } ret = 0; fail_or_end: aligned_free(ref_buf); aligned_free(dis_buf); aligned_free(temp_buf); return ret; }
int adm(const char *ref_path, const char *dis_path, int w, int h, const char *fmt) { double score = 0; double score_num = 0; double score_den = 0; double scores[2*4]; number_t *ref_buf = 0; number_t *dis_buf = 0; number_t *temp_buf = 0; FILE *ref_rfile = 0; FILE *dis_rfile = 0; size_t data_sz; int stride; int ret = 1; if (w <= 0 || h <= 0 || (size_t)w > ALIGN_FLOOR(INT_MAX) / sizeof(number_t)) { goto fail_or_end; } stride = ALIGN_CEIL(w * sizeof(number_t)); if ((size_t)h > SIZE_MAX / stride) { goto fail_or_end; } data_sz = (size_t)stride * h; if (!(ref_buf = aligned_malloc(data_sz, MAX_ALIGN))) { printf("error: aligned_malloc failed for ref_buf.\n"); fflush(stdout); goto fail_or_end; } if (!(dis_buf = aligned_malloc(data_sz, MAX_ALIGN))) { printf("error: aligned_malloc failed for dis_buf.\n"); fflush(stdout); goto fail_or_end; } if (!(temp_buf = aligned_malloc(data_sz * 2, MAX_ALIGN))) { printf("error: aligned_malloc failed for temp_buf.\n"); fflush(stdout); goto fail_or_end; } if (!(ref_rfile = fopen(ref_path, "rb"))) { printf("error: fopen ref_path %s failed\n", ref_path); fflush(stdout); goto fail_or_end; } if (!(dis_rfile = fopen(dis_path, "rb"))) { printf("error: fopen dis_path %s failed.\n", dis_path); fflush(stdout); goto fail_or_end; } size_t offset; if (!strcmp(fmt, "yuv420p") || !strcmp(fmt, "yuv420p10le")) { if ((w * h) % 2 != 0) { printf("error: (w * h) %% 2 != 0, w = %d, h = %d.\n", w, h); fflush(stdout); goto fail_or_end; } offset = w * h / 2; } else if (!strcmp(fmt, "yuv422p") || !strcmp(fmt, "yuv422p10le")) { offset = w * h; } else if (!strcmp(fmt, "yuv444p") || !strcmp(fmt, "yuv444p10le")) { offset = w * h * 2; } else { printf("error: unknown format %s.\n", fmt); fflush(stdout); goto fail_or_end; } int frm_idx = 0; while (1) { // read ref y if (!strcmp(fmt, "yuv420p") || !strcmp(fmt, "yuv422p") || !strcmp(fmt, "yuv444p")) { ret = read_image_b(ref_rfile, ref_buf, OPT_RANGE_PIXEL_OFFSET, w, h, stride); } else if (!strcmp(fmt, "yuv420p10le") || !strcmp(fmt, "yuv422p10le") || !strcmp(fmt, "yuv444p10le")) { ret = read_image_w(ref_rfile, ref_buf, OPT_RANGE_PIXEL_OFFSET, w, h, stride); } else { printf("error: unknown format %s.\n", fmt); fflush(stdout); goto fail_or_end; } if (ret) { if (feof(ref_rfile)) { ret = 0; // OK if end of file } goto fail_or_end; } // read dis y if (!strcmp(fmt, "yuv420p") || !strcmp(fmt, "yuv422p") || !strcmp(fmt, "yuv444p")) { ret = read_image_b(dis_rfile, dis_buf, OPT_RANGE_PIXEL_OFFSET, w, h, stride); } else if (!strcmp(fmt, "yuv420p10le") || !strcmp(fmt, "yuv422p10le") || !strcmp(fmt, "yuv444p10le")) { ret = read_image_w(dis_rfile, dis_buf, OPT_RANGE_PIXEL_OFFSET, w, h, stride); } else { printf("error: unknown format %s.\n", fmt); fflush(stdout); goto fail_or_end; } if (ret) { if (feof(dis_rfile)) { ret = 0; // OK if end of file } goto fail_or_end; } // compute if ((ret = compute_adm(ref_buf, dis_buf, w, h, stride, stride, &score, &score_num, &score_den, scores, ADM_BORDER_FACTOR))) { printf("error: compute_adm failed.\n"); fflush(stdout); goto fail_or_end; } // print printf("adm: %d %f\n", frm_idx, score); fflush(stdout); printf("adm_num: %d %f\n", frm_idx, score_num); fflush(stdout); printf("adm_den: %d %f\n", frm_idx, score_den); fflush(stdout); for(int scale=0;scale<4;scale++) { printf("adm_num_scale%d: %d %f\n", scale, frm_idx, scores[2*scale]); fflush(stdout); printf("adm_den_scale%d: %d %f\n", scale, frm_idx, scores[2*scale+1]); fflush(stdout); } // ref skip u and v if (!strcmp(fmt, "yuv420p") || !strcmp(fmt, "yuv422p") || !strcmp(fmt, "yuv444p")) { if (fread(temp_buf, 1, offset, ref_rfile) != (size_t)offset) { printf("error: ref fread u and v failed.\n"); fflush(stdout); goto fail_or_end; } } else if (!strcmp(fmt, "yuv420p10le") || !strcmp(fmt, "yuv422p10le") || !strcmp(fmt, "yuv444p10le")) { if (fread(temp_buf, 2, offset, ref_rfile) != (size_t)offset) { printf("error: ref fread u and v failed.\n"); fflush(stdout); goto fail_or_end; } } else { printf("error: unknown format %s.\n", fmt); fflush(stdout); goto fail_or_end; } // dis skip u and v if (!strcmp(fmt, "yuv420p") || !strcmp(fmt, "yuv422p") || !strcmp(fmt, "yuv444p")) { if (fread(temp_buf, 1, offset, dis_rfile) != (size_t)offset) { printf("error: dis fread u and v failed.\n"); fflush(stdout); goto fail_or_end; } } else if (!strcmp(fmt, "yuv420p10le") || !strcmp(fmt, "yuv422p10le") || !strcmp(fmt, "yuv444p10le")) { if (fread(temp_buf, 2, offset, dis_rfile) != (size_t)offset) { printf("error: dis fread u and v failed.\n"); fflush(stdout); goto fail_or_end; } } else { printf("error: unknown format %s.\n", fmt); fflush(stdout); goto fail_or_end; } frm_idx++; } ret = 0; fail_or_end: if (ref_rfile) { fclose(ref_rfile); } if (dis_rfile) { fclose(dis_rfile); } aligned_free(ref_buf); aligned_free(dis_buf); aligned_free(temp_buf); return ret; }
int psnr(const char *ref_path, const char *dis_path, int w, int h, const char *fmt) { double score = 0; number_t *ref_buf = 0; number_t *dis_buf = 0; number_t *temp_buf = 0; FILE *ref_rfile = 0; FILE *dis_rfile = 0; size_t data_sz; int stride; int ret = 1; if (w <= 0 || h <= 0 || (size_t)w > ALIGN_FLOOR(INT_MAX) / sizeof(number_t)) { goto fail_or_end; } stride = ALIGN_CEIL(w * sizeof(number_t)); if ((size_t)h > SIZE_MAX / stride) { goto fail_or_end; } data_sz = (size_t)stride * h; if (!(ref_buf = aligned_malloc(data_sz, MAX_ALIGN))) { printf("error: aligned_malloc failed for ref_buf.\n"); fflush(stdout); goto fail_or_end; } if (!(dis_buf = aligned_malloc(data_sz, MAX_ALIGN))) { printf("error: aligned_malloc failed for dis_buf.\n"); fflush(stdout); goto fail_or_end; } if (!(temp_buf = aligned_malloc(data_sz * 2, MAX_ALIGN))) { printf("error: aligned_malloc failed for temp_buf.\n"); fflush(stdout); goto fail_or_end; } if (!(ref_rfile = fopen(ref_path, "rb"))) { printf("error: fopen ref_path %s failed\n", ref_path); fflush(stdout); goto fail_or_end; } if (!(dis_rfile = fopen(dis_path, "rb"))) { printf("error: fopen dis_path %s failed.\n", dis_path); fflush(stdout); goto fail_or_end; } size_t offset; if (!strcmp(fmt, "yuv420p") || !strcmp(fmt, "yuv420p10le")) { if ((w * h) % 2 != 0) { printf("error: (w * h) %% 2 != 0, w = %d, h = %d.\n", w, h); fflush(stdout); goto fail_or_end; } offset = w * h / 2; } else if (!strcmp(fmt, "yuv422p") || !strcmp(fmt, "yuv422p10le")) { offset = w * h; } else if (!strcmp(fmt, "yuv444p") || !strcmp(fmt, "yuv444p10le")) { offset = w * h * 2; } else { printf("error: unknown format %s.\n", fmt); fflush(stdout); goto fail_or_end; } int frm_idx = 0; while ((!feof(ref_rfile)) && (!feof(dis_rfile))) { // read ref y if (!strcmp(fmt, "yuv420p") || !strcmp(fmt, "yuv422p") || !strcmp(fmt, "yuv444p")) { ret = read_image_b(ref_rfile, ref_buf, 0, w, h, stride); } else if (!strcmp(fmt, "yuv420p10le") || !strcmp(fmt, "yuv422p10le") || !strcmp(fmt, "yuv444p10le")) { ret = read_image_w(ref_rfile, ref_buf, 0, w, h, stride); } else { printf("error: unknown format %s.\n", fmt); fflush(stdout); goto fail_or_end; } if (ret) { goto fail_or_end; } // read dis y if (!strcmp(fmt, "yuv420p") || !strcmp(fmt, "yuv422p") || !strcmp(fmt, "yuv444p")) { ret = read_image_b(dis_rfile, dis_buf, 0, w, h, stride); } else if (!strcmp(fmt, "yuv420p10le") || !strcmp(fmt, "yuv422p10le") || !strcmp(fmt, "yuv444p10le")) { ret = read_image_w(dis_rfile, dis_buf, 0, w, h, stride); } else { printf("error: unknown format %s.\n", fmt); fflush(stdout); goto fail_or_end; } if (ret) { goto fail_or_end; } // compute if (!strcmp(fmt, "yuv420p") || !strcmp(fmt, "yuv422p") || !strcmp(fmt, "yuv444p")) { // max psnr 60.0 for 8-bit per Ioannis ret = compute_psnr(ref_buf, dis_buf, w, h, stride, stride, &score, 255.0, 60.0); } else if (!strcmp(fmt, "yuv420p10le") || !strcmp(fmt, "yuv422p10le") || !strcmp(fmt, "yuv444p10le")) { // 10 bit gets normalized to 8 bit, peak is 1023 / 4.0 = 255.75 // max psnr 72.0 for 10-bit per Ioannis ret = compute_psnr(ref_buf, dis_buf, w, h, stride, stride, &score, 255.75, 72.0); } else { printf("error: unknown format %s.\n", fmt); fflush(stdout); goto fail_or_end; } if (ret) { printf("error: compute_psnr failed.\n"); fflush(stdout); goto fail_or_end; } // print printf("psnr: %d %f\n", frm_idx, score); fflush(stdout); // ref skip u and v if (!strcmp(fmt, "yuv420p") || !strcmp(fmt, "yuv422p") || !strcmp(fmt, "yuv444p")) { if (fread(temp_buf, 1, offset, ref_rfile) != (size_t)offset) { printf("error: ref fread u and v failed.\n"); fflush(stdout); goto fail_or_end; } } else if (!strcmp(fmt, "yuv420p10le") || !strcmp(fmt, "yuv422p10le") || !strcmp(fmt, "yuv444p10le")) { if (fread(temp_buf, 2, offset, ref_rfile) != (size_t)offset) { printf("error: ref fread u and v failed.\n"); fflush(stdout); goto fail_or_end; } } else { printf("error: unknown format %s.\n", fmt); fflush(stdout); goto fail_or_end; } // dis skip u and v if (!strcmp(fmt, "yuv420p") || !strcmp(fmt, "yuv422p") || !strcmp(fmt, "yuv444p")) { if (fread(temp_buf, 1, offset, dis_rfile) != (size_t)offset) { printf("error: dis fread u and v failed.\n"); fflush(stdout); goto fail_or_end; } } else if (!strcmp(fmt, "yuv420p10le") || !strcmp(fmt, "yuv422p10le") || !strcmp(fmt, "yuv444p10le")) { if (fread(temp_buf, 2, offset, dis_rfile) != (size_t)offset) { printf("error: dis fread u and v failed.\n"); fflush(stdout); goto fail_or_end; } } else { printf("error: unknown format %s.\n", fmt); fflush(stdout); goto fail_or_end; } frm_idx++; } ret = 0; fail_or_end: if (ref_rfile) { fclose(ref_rfile); } if (dis_rfile) { fclose(dis_rfile); } aligned_free(ref_buf); aligned_free(dis_buf); aligned_free(temp_buf); return ret; }