1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker * Copyright (c) 2016 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker *
4*fb1b10abSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker */
10*fb1b10abSAndroid Build Coastguard Worker
11*fb1b10abSAndroid Build Coastguard Worker #include <assert.h>
12*fb1b10abSAndroid Build Coastguard Worker #include <errno.h>
13*fb1b10abSAndroid Build Coastguard Worker #include <math.h>
14*fb1b10abSAndroid Build Coastguard Worker #include <stdio.h>
15*fb1b10abSAndroid Build Coastguard Worker #include <stdlib.h>
16*fb1b10abSAndroid Build Coastguard Worker #include <string.h>
17*fb1b10abSAndroid Build Coastguard Worker #include "vpx/vpx_codec.h"
18*fb1b10abSAndroid Build Coastguard Worker #include "vpx/vpx_integer.h"
19*fb1b10abSAndroid Build Coastguard Worker #include "./y4minput.h"
20*fb1b10abSAndroid Build Coastguard Worker #include "vpx_dsp/ssim.h"
21*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/mem.h"
22*fb1b10abSAndroid Build Coastguard Worker
23*fb1b10abSAndroid Build Coastguard Worker static const int64_t cc1 = 26634; // (64^2*(.01*255)^2
24*fb1b10abSAndroid Build Coastguard Worker static const int64_t cc2 = 239708; // (64^2*(.03*255)^2
25*fb1b10abSAndroid Build Coastguard Worker static const int64_t cc1_10 = 428658; // (64^2*(.01*1023)^2
26*fb1b10abSAndroid Build Coastguard Worker static const int64_t cc2_10 = 3857925; // (64^2*(.03*1023)^2
27*fb1b10abSAndroid Build Coastguard Worker static const int64_t cc1_12 = 6868593; // (64^2*(.01*4095)^2
28*fb1b10abSAndroid Build Coastguard Worker static const int64_t cc2_12 = 61817334; // (64^2*(.03*4095)^2
29*fb1b10abSAndroid Build Coastguard Worker
30*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
calc_plane_error16(uint16_t * orig,int orig_stride,uint16_t * recon,int recon_stride,unsigned int cols,unsigned int rows)31*fb1b10abSAndroid Build Coastguard Worker static uint64_t calc_plane_error16(uint16_t *orig, int orig_stride,
32*fb1b10abSAndroid Build Coastguard Worker uint16_t *recon, int recon_stride,
33*fb1b10abSAndroid Build Coastguard Worker unsigned int cols, unsigned int rows) {
34*fb1b10abSAndroid Build Coastguard Worker unsigned int row, col;
35*fb1b10abSAndroid Build Coastguard Worker uint64_t total_sse = 0;
36*fb1b10abSAndroid Build Coastguard Worker int diff;
37*fb1b10abSAndroid Build Coastguard Worker if (orig == NULL || recon == NULL) {
38*fb1b10abSAndroid Build Coastguard Worker assert(0);
39*fb1b10abSAndroid Build Coastguard Worker return 0;
40*fb1b10abSAndroid Build Coastguard Worker }
41*fb1b10abSAndroid Build Coastguard Worker
42*fb1b10abSAndroid Build Coastguard Worker for (row = 0; row < rows; row++) {
43*fb1b10abSAndroid Build Coastguard Worker for (col = 0; col < cols; col++) {
44*fb1b10abSAndroid Build Coastguard Worker diff = orig[col] - recon[col];
45*fb1b10abSAndroid Build Coastguard Worker total_sse += diff * diff;
46*fb1b10abSAndroid Build Coastguard Worker }
47*fb1b10abSAndroid Build Coastguard Worker
48*fb1b10abSAndroid Build Coastguard Worker orig += orig_stride;
49*fb1b10abSAndroid Build Coastguard Worker recon += recon_stride;
50*fb1b10abSAndroid Build Coastguard Worker }
51*fb1b10abSAndroid Build Coastguard Worker return total_sse;
52*fb1b10abSAndroid Build Coastguard Worker }
53*fb1b10abSAndroid Build Coastguard Worker #endif // CONFIG_VP9_HIGHBITDEPTH
54*fb1b10abSAndroid Build Coastguard Worker
calc_plane_error(uint8_t * orig,int orig_stride,uint8_t * recon,int recon_stride,unsigned int cols,unsigned int rows)55*fb1b10abSAndroid Build Coastguard Worker static uint64_t calc_plane_error(uint8_t *orig, int orig_stride, uint8_t *recon,
56*fb1b10abSAndroid Build Coastguard Worker int recon_stride, unsigned int cols,
57*fb1b10abSAndroid Build Coastguard Worker unsigned int rows) {
58*fb1b10abSAndroid Build Coastguard Worker unsigned int row, col;
59*fb1b10abSAndroid Build Coastguard Worker uint64_t total_sse = 0;
60*fb1b10abSAndroid Build Coastguard Worker int diff;
61*fb1b10abSAndroid Build Coastguard Worker if (orig == NULL || recon == NULL) {
62*fb1b10abSAndroid Build Coastguard Worker assert(0);
63*fb1b10abSAndroid Build Coastguard Worker return 0;
64*fb1b10abSAndroid Build Coastguard Worker }
65*fb1b10abSAndroid Build Coastguard Worker
66*fb1b10abSAndroid Build Coastguard Worker for (row = 0; row < rows; row++) {
67*fb1b10abSAndroid Build Coastguard Worker for (col = 0; col < cols; col++) {
68*fb1b10abSAndroid Build Coastguard Worker diff = orig[col] - recon[col];
69*fb1b10abSAndroid Build Coastguard Worker total_sse += diff * diff;
70*fb1b10abSAndroid Build Coastguard Worker }
71*fb1b10abSAndroid Build Coastguard Worker
72*fb1b10abSAndroid Build Coastguard Worker orig += orig_stride;
73*fb1b10abSAndroid Build Coastguard Worker recon += recon_stride;
74*fb1b10abSAndroid Build Coastguard Worker }
75*fb1b10abSAndroid Build Coastguard Worker return total_sse;
76*fb1b10abSAndroid Build Coastguard Worker }
77*fb1b10abSAndroid Build Coastguard Worker
78*fb1b10abSAndroid Build Coastguard Worker #define MAX_PSNR 100
mse2psnr(double samples,double peak,double mse)79*fb1b10abSAndroid Build Coastguard Worker static double mse2psnr(double samples, double peak, double mse) {
80*fb1b10abSAndroid Build Coastguard Worker double psnr;
81*fb1b10abSAndroid Build Coastguard Worker
82*fb1b10abSAndroid Build Coastguard Worker if (mse > 0.0)
83*fb1b10abSAndroid Build Coastguard Worker psnr = 10.0 * log10(peak * peak * samples / mse);
84*fb1b10abSAndroid Build Coastguard Worker else
85*fb1b10abSAndroid Build Coastguard Worker psnr = MAX_PSNR; // Limit to prevent / 0
86*fb1b10abSAndroid Build Coastguard Worker
87*fb1b10abSAndroid Build Coastguard Worker if (psnr > MAX_PSNR) psnr = MAX_PSNR;
88*fb1b10abSAndroid Build Coastguard Worker
89*fb1b10abSAndroid Build Coastguard Worker return psnr;
90*fb1b10abSAndroid Build Coastguard Worker }
91*fb1b10abSAndroid Build Coastguard Worker
92*fb1b10abSAndroid Build Coastguard Worker typedef enum { RAW_YUV, Y4M } input_file_type;
93*fb1b10abSAndroid Build Coastguard Worker
94*fb1b10abSAndroid Build Coastguard Worker typedef struct input_file {
95*fb1b10abSAndroid Build Coastguard Worker FILE *file;
96*fb1b10abSAndroid Build Coastguard Worker input_file_type type;
97*fb1b10abSAndroid Build Coastguard Worker unsigned char *buf;
98*fb1b10abSAndroid Build Coastguard Worker y4m_input y4m;
99*fb1b10abSAndroid Build Coastguard Worker vpx_image_t img;
100*fb1b10abSAndroid Build Coastguard Worker int w;
101*fb1b10abSAndroid Build Coastguard Worker int h;
102*fb1b10abSAndroid Build Coastguard Worker int bit_depth;
103*fb1b10abSAndroid Build Coastguard Worker int frame_size;
104*fb1b10abSAndroid Build Coastguard Worker } input_file_t;
105*fb1b10abSAndroid Build Coastguard Worker
106*fb1b10abSAndroid Build Coastguard Worker // Open a file and determine if its y4m or raw. If y4m get the header.
open_input_file(const char * file_name,input_file_t * input,int w,int h,int bit_depth)107*fb1b10abSAndroid Build Coastguard Worker static int open_input_file(const char *file_name, input_file_t *input, int w,
108*fb1b10abSAndroid Build Coastguard Worker int h, int bit_depth) {
109*fb1b10abSAndroid Build Coastguard Worker char y4m_buf[4];
110*fb1b10abSAndroid Build Coastguard Worker input->w = w;
111*fb1b10abSAndroid Build Coastguard Worker input->h = h;
112*fb1b10abSAndroid Build Coastguard Worker input->bit_depth = bit_depth;
113*fb1b10abSAndroid Build Coastguard Worker input->type = RAW_YUV;
114*fb1b10abSAndroid Build Coastguard Worker input->buf = NULL;
115*fb1b10abSAndroid Build Coastguard Worker input->file = strcmp(file_name, "-") ? fopen(file_name, "rb") : stdin;
116*fb1b10abSAndroid Build Coastguard Worker if (input->file == NULL) return -1;
117*fb1b10abSAndroid Build Coastguard Worker if (fread(y4m_buf, 1, 4, input->file) != 4) return -1;
118*fb1b10abSAndroid Build Coastguard Worker if (memcmp(y4m_buf, "YUV4", 4) == 0) input->type = Y4M;
119*fb1b10abSAndroid Build Coastguard Worker switch (input->type) {
120*fb1b10abSAndroid Build Coastguard Worker case Y4M:
121*fb1b10abSAndroid Build Coastguard Worker y4m_input_open(&input->y4m, input->file, y4m_buf, 4, 0);
122*fb1b10abSAndroid Build Coastguard Worker input->w = input->y4m.pic_w;
123*fb1b10abSAndroid Build Coastguard Worker input->h = input->y4m.pic_h;
124*fb1b10abSAndroid Build Coastguard Worker input->bit_depth = input->y4m.bit_depth;
125*fb1b10abSAndroid Build Coastguard Worker // Y4M alloc's its own buf. Init this to avoid problems if we never
126*fb1b10abSAndroid Build Coastguard Worker // read frames.
127*fb1b10abSAndroid Build Coastguard Worker memset(&input->img, 0, sizeof(input->img));
128*fb1b10abSAndroid Build Coastguard Worker break;
129*fb1b10abSAndroid Build Coastguard Worker case RAW_YUV:
130*fb1b10abSAndroid Build Coastguard Worker fseek(input->file, 0, SEEK_SET);
131*fb1b10abSAndroid Build Coastguard Worker input->w = w;
132*fb1b10abSAndroid Build Coastguard Worker input->h = h;
133*fb1b10abSAndroid Build Coastguard Worker // handle odd frame sizes
134*fb1b10abSAndroid Build Coastguard Worker input->frame_size = w * h + ((w + 1) / 2) * ((h + 1) / 2) * 2;
135*fb1b10abSAndroid Build Coastguard Worker if (bit_depth > 8) {
136*fb1b10abSAndroid Build Coastguard Worker input->frame_size *= 2;
137*fb1b10abSAndroid Build Coastguard Worker }
138*fb1b10abSAndroid Build Coastguard Worker input->buf = malloc(input->frame_size);
139*fb1b10abSAndroid Build Coastguard Worker break;
140*fb1b10abSAndroid Build Coastguard Worker }
141*fb1b10abSAndroid Build Coastguard Worker return 0;
142*fb1b10abSAndroid Build Coastguard Worker }
143*fb1b10abSAndroid Build Coastguard Worker
close_input_file(input_file_t * in)144*fb1b10abSAndroid Build Coastguard Worker static void close_input_file(input_file_t *in) {
145*fb1b10abSAndroid Build Coastguard Worker if (in->file) fclose(in->file);
146*fb1b10abSAndroid Build Coastguard Worker if (in->type == Y4M) {
147*fb1b10abSAndroid Build Coastguard Worker vpx_img_free(&in->img);
148*fb1b10abSAndroid Build Coastguard Worker } else {
149*fb1b10abSAndroid Build Coastguard Worker free(in->buf);
150*fb1b10abSAndroid Build Coastguard Worker }
151*fb1b10abSAndroid Build Coastguard Worker }
152*fb1b10abSAndroid Build Coastguard Worker
153*fb1b10abSAndroid Build Coastguard Worker // Returns 1 on success, 0 on failure due to a read error or eof (or format
154*fb1b10abSAndroid Build Coastguard Worker // error in the case of y4m).
read_input_file(input_file_t * in,unsigned char ** y,unsigned char ** u,unsigned char ** v,int bd)155*fb1b10abSAndroid Build Coastguard Worker static int read_input_file(input_file_t *in, unsigned char **y,
156*fb1b10abSAndroid Build Coastguard Worker unsigned char **u, unsigned char **v, int bd) {
157*fb1b10abSAndroid Build Coastguard Worker size_t r1 = 0;
158*fb1b10abSAndroid Build Coastguard Worker switch (in->type) {
159*fb1b10abSAndroid Build Coastguard Worker case Y4M:
160*fb1b10abSAndroid Build Coastguard Worker r1 = y4m_input_fetch_frame(&in->y4m, in->file, &in->img);
161*fb1b10abSAndroid Build Coastguard Worker if (r1 == (size_t)-1) return 0;
162*fb1b10abSAndroid Build Coastguard Worker *y = in->img.planes[0];
163*fb1b10abSAndroid Build Coastguard Worker *u = in->img.planes[1];
164*fb1b10abSAndroid Build Coastguard Worker *v = in->img.planes[2];
165*fb1b10abSAndroid Build Coastguard Worker break;
166*fb1b10abSAndroid Build Coastguard Worker case RAW_YUV:
167*fb1b10abSAndroid Build Coastguard Worker if (bd < 9) {
168*fb1b10abSAndroid Build Coastguard Worker r1 = fread(in->buf, in->frame_size, 1, in->file);
169*fb1b10abSAndroid Build Coastguard Worker *y = in->buf;
170*fb1b10abSAndroid Build Coastguard Worker *u = in->buf + in->w * in->h;
171*fb1b10abSAndroid Build Coastguard Worker *v = *u + ((1 + in->w) / 2) * ((1 + in->h) / 2);
172*fb1b10abSAndroid Build Coastguard Worker } else {
173*fb1b10abSAndroid Build Coastguard Worker r1 = fread(in->buf, in->frame_size, 1, in->file);
174*fb1b10abSAndroid Build Coastguard Worker *y = in->buf;
175*fb1b10abSAndroid Build Coastguard Worker *u = in->buf + (in->w * in->h) * 2;
176*fb1b10abSAndroid Build Coastguard Worker *v = *u + 2 * ((1 + in->w) / 2) * ((1 + in->h) / 2);
177*fb1b10abSAndroid Build Coastguard Worker }
178*fb1b10abSAndroid Build Coastguard Worker break;
179*fb1b10abSAndroid Build Coastguard Worker }
180*fb1b10abSAndroid Build Coastguard Worker
181*fb1b10abSAndroid Build Coastguard Worker return r1 != 0;
182*fb1b10abSAndroid Build Coastguard Worker }
183*fb1b10abSAndroid Build Coastguard Worker
ssim_parms_8x8(const uint8_t * s,int sp,const uint8_t * r,int rp,uint32_t * sum_s,uint32_t * sum_r,uint32_t * sum_sq_s,uint32_t * sum_sq_r,uint32_t * sum_sxr)184*fb1b10abSAndroid Build Coastguard Worker static void ssim_parms_8x8(const uint8_t *s, int sp, const uint8_t *r, int rp,
185*fb1b10abSAndroid Build Coastguard Worker uint32_t *sum_s, uint32_t *sum_r, uint32_t *sum_sq_s,
186*fb1b10abSAndroid Build Coastguard Worker uint32_t *sum_sq_r, uint32_t *sum_sxr) {
187*fb1b10abSAndroid Build Coastguard Worker int i, j;
188*fb1b10abSAndroid Build Coastguard Worker if (s == NULL || r == NULL || sum_s == NULL || sum_r == NULL ||
189*fb1b10abSAndroid Build Coastguard Worker sum_sq_s == NULL || sum_sq_r == NULL || sum_sxr == NULL) {
190*fb1b10abSAndroid Build Coastguard Worker assert(0);
191*fb1b10abSAndroid Build Coastguard Worker return;
192*fb1b10abSAndroid Build Coastguard Worker }
193*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < 8; i++, s += sp, r += rp) {
194*fb1b10abSAndroid Build Coastguard Worker for (j = 0; j < 8; j++) {
195*fb1b10abSAndroid Build Coastguard Worker *sum_s += s[j];
196*fb1b10abSAndroid Build Coastguard Worker *sum_r += r[j];
197*fb1b10abSAndroid Build Coastguard Worker *sum_sq_s += s[j] * s[j];
198*fb1b10abSAndroid Build Coastguard Worker *sum_sq_r += r[j] * r[j];
199*fb1b10abSAndroid Build Coastguard Worker *sum_sxr += s[j] * r[j];
200*fb1b10abSAndroid Build Coastguard Worker }
201*fb1b10abSAndroid Build Coastguard Worker }
202*fb1b10abSAndroid Build Coastguard Worker }
203*fb1b10abSAndroid Build Coastguard Worker
204*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
highbd_ssim_parms_8x8(const uint16_t * s,int sp,const uint16_t * r,int rp,uint32_t * sum_s,uint32_t * sum_r,uint32_t * sum_sq_s,uint32_t * sum_sq_r,uint32_t * sum_sxr)205*fb1b10abSAndroid Build Coastguard Worker static void highbd_ssim_parms_8x8(const uint16_t *s, int sp, const uint16_t *r,
206*fb1b10abSAndroid Build Coastguard Worker int rp, uint32_t *sum_s, uint32_t *sum_r,
207*fb1b10abSAndroid Build Coastguard Worker uint32_t *sum_sq_s, uint32_t *sum_sq_r,
208*fb1b10abSAndroid Build Coastguard Worker uint32_t *sum_sxr) {
209*fb1b10abSAndroid Build Coastguard Worker int i, j;
210*fb1b10abSAndroid Build Coastguard Worker if (s == NULL || r == NULL || sum_s == NULL || sum_r == NULL ||
211*fb1b10abSAndroid Build Coastguard Worker sum_sq_s == NULL || sum_sq_r == NULL || sum_sxr == NULL) {
212*fb1b10abSAndroid Build Coastguard Worker assert(0);
213*fb1b10abSAndroid Build Coastguard Worker return;
214*fb1b10abSAndroid Build Coastguard Worker }
215*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < 8; i++, s += sp, r += rp) {
216*fb1b10abSAndroid Build Coastguard Worker for (j = 0; j < 8; j++) {
217*fb1b10abSAndroid Build Coastguard Worker *sum_s += s[j];
218*fb1b10abSAndroid Build Coastguard Worker *sum_r += r[j];
219*fb1b10abSAndroid Build Coastguard Worker *sum_sq_s += s[j] * s[j];
220*fb1b10abSAndroid Build Coastguard Worker *sum_sq_r += r[j] * r[j];
221*fb1b10abSAndroid Build Coastguard Worker *sum_sxr += s[j] * r[j];
222*fb1b10abSAndroid Build Coastguard Worker }
223*fb1b10abSAndroid Build Coastguard Worker }
224*fb1b10abSAndroid Build Coastguard Worker }
225*fb1b10abSAndroid Build Coastguard Worker #endif // CONFIG_VP9_HIGHBITDEPTH
226*fb1b10abSAndroid Build Coastguard Worker
similarity(uint32_t sum_s,uint32_t sum_r,uint32_t sum_sq_s,uint32_t sum_sq_r,uint32_t sum_sxr,int count,uint32_t bd)227*fb1b10abSAndroid Build Coastguard Worker static double similarity(uint32_t sum_s, uint32_t sum_r, uint32_t sum_sq_s,
228*fb1b10abSAndroid Build Coastguard Worker uint32_t sum_sq_r, uint32_t sum_sxr, int count,
229*fb1b10abSAndroid Build Coastguard Worker uint32_t bd) {
230*fb1b10abSAndroid Build Coastguard Worker double ssim_n, ssim_d;
231*fb1b10abSAndroid Build Coastguard Worker int64_t c1 = 0, c2 = 0;
232*fb1b10abSAndroid Build Coastguard Worker if (bd == 8) {
233*fb1b10abSAndroid Build Coastguard Worker // scale the constants by number of pixels
234*fb1b10abSAndroid Build Coastguard Worker c1 = (cc1 * count * count) >> 12;
235*fb1b10abSAndroid Build Coastguard Worker c2 = (cc2 * count * count) >> 12;
236*fb1b10abSAndroid Build Coastguard Worker } else if (bd == 10) {
237*fb1b10abSAndroid Build Coastguard Worker c1 = (cc1_10 * count * count) >> 12;
238*fb1b10abSAndroid Build Coastguard Worker c2 = (cc2_10 * count * count) >> 12;
239*fb1b10abSAndroid Build Coastguard Worker } else if (bd == 12) {
240*fb1b10abSAndroid Build Coastguard Worker c1 = (cc1_12 * count * count) >> 12;
241*fb1b10abSAndroid Build Coastguard Worker c2 = (cc2_12 * count * count) >> 12;
242*fb1b10abSAndroid Build Coastguard Worker } else {
243*fb1b10abSAndroid Build Coastguard Worker assert(0);
244*fb1b10abSAndroid Build Coastguard Worker }
245*fb1b10abSAndroid Build Coastguard Worker
246*fb1b10abSAndroid Build Coastguard Worker ssim_n = (2.0 * sum_s * sum_r + c1) *
247*fb1b10abSAndroid Build Coastguard Worker (2.0 * count * sum_sxr - 2.0 * sum_s * sum_r + c2);
248*fb1b10abSAndroid Build Coastguard Worker
249*fb1b10abSAndroid Build Coastguard Worker ssim_d = ((double)sum_s * sum_s + (double)sum_r * sum_r + c1) *
250*fb1b10abSAndroid Build Coastguard Worker ((double)count * sum_sq_s - (double)sum_s * sum_s +
251*fb1b10abSAndroid Build Coastguard Worker (double)count * sum_sq_r - (double)sum_r * sum_r + c2);
252*fb1b10abSAndroid Build Coastguard Worker
253*fb1b10abSAndroid Build Coastguard Worker return ssim_n / ssim_d;
254*fb1b10abSAndroid Build Coastguard Worker }
255*fb1b10abSAndroid Build Coastguard Worker
ssim_8x8(const uint8_t * s,int sp,const uint8_t * r,int rp)256*fb1b10abSAndroid Build Coastguard Worker static double ssim_8x8(const uint8_t *s, int sp, const uint8_t *r, int rp) {
257*fb1b10abSAndroid Build Coastguard Worker uint32_t sum_s = 0, sum_r = 0, sum_sq_s = 0, sum_sq_r = 0, sum_sxr = 0;
258*fb1b10abSAndroid Build Coastguard Worker ssim_parms_8x8(s, sp, r, rp, &sum_s, &sum_r, &sum_sq_s, &sum_sq_r, &sum_sxr);
259*fb1b10abSAndroid Build Coastguard Worker return similarity(sum_s, sum_r, sum_sq_s, sum_sq_r, sum_sxr, 64, 8);
260*fb1b10abSAndroid Build Coastguard Worker }
261*fb1b10abSAndroid Build Coastguard Worker
262*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
highbd_ssim_8x8(const uint16_t * s,int sp,const uint16_t * r,int rp,uint32_t bd)263*fb1b10abSAndroid Build Coastguard Worker static double highbd_ssim_8x8(const uint16_t *s, int sp, const uint16_t *r,
264*fb1b10abSAndroid Build Coastguard Worker int rp, uint32_t bd) {
265*fb1b10abSAndroid Build Coastguard Worker uint32_t sum_s = 0, sum_r = 0, sum_sq_s = 0, sum_sq_r = 0, sum_sxr = 0;
266*fb1b10abSAndroid Build Coastguard Worker highbd_ssim_parms_8x8(s, sp, r, rp, &sum_s, &sum_r, &sum_sq_s, &sum_sq_r,
267*fb1b10abSAndroid Build Coastguard Worker &sum_sxr);
268*fb1b10abSAndroid Build Coastguard Worker return similarity(sum_s, sum_r, sum_sq_s, sum_sq_r, sum_sxr, 64, bd);
269*fb1b10abSAndroid Build Coastguard Worker }
270*fb1b10abSAndroid Build Coastguard Worker #endif // CONFIG_VP9_HIGHBITDEPTH
271*fb1b10abSAndroid Build Coastguard Worker
272*fb1b10abSAndroid Build Coastguard Worker // We are using a 8x8 moving window with starting location of each 8x8 window
273*fb1b10abSAndroid Build Coastguard Worker // on the 4x4 pixel grid. Such arrangement allows the windows to overlap
274*fb1b10abSAndroid Build Coastguard Worker // block boundaries to penalize blocking artifacts.
ssim2(const uint8_t * img1,const uint8_t * img2,int stride_img1,int stride_img2,int width,int height)275*fb1b10abSAndroid Build Coastguard Worker static double ssim2(const uint8_t *img1, const uint8_t *img2, int stride_img1,
276*fb1b10abSAndroid Build Coastguard Worker int stride_img2, int width, int height) {
277*fb1b10abSAndroid Build Coastguard Worker int i, j;
278*fb1b10abSAndroid Build Coastguard Worker int samples = 0;
279*fb1b10abSAndroid Build Coastguard Worker double ssim_total = 0;
280*fb1b10abSAndroid Build Coastguard Worker
281*fb1b10abSAndroid Build Coastguard Worker // sample point start with each 4x4 location
282*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i <= height - 8;
283*fb1b10abSAndroid Build Coastguard Worker i += 4, img1 += stride_img1 * 4, img2 += stride_img2 * 4) {
284*fb1b10abSAndroid Build Coastguard Worker for (j = 0; j <= width - 8; j += 4) {
285*fb1b10abSAndroid Build Coastguard Worker double v = ssim_8x8(img1 + j, stride_img1, img2 + j, stride_img2);
286*fb1b10abSAndroid Build Coastguard Worker ssim_total += v;
287*fb1b10abSAndroid Build Coastguard Worker samples++;
288*fb1b10abSAndroid Build Coastguard Worker }
289*fb1b10abSAndroid Build Coastguard Worker }
290*fb1b10abSAndroid Build Coastguard Worker ssim_total /= samples;
291*fb1b10abSAndroid Build Coastguard Worker return ssim_total;
292*fb1b10abSAndroid Build Coastguard Worker }
293*fb1b10abSAndroid Build Coastguard Worker
294*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
highbd_ssim2(const uint8_t * img1,const uint8_t * img2,int stride_img1,int stride_img2,int width,int height,uint32_t bd)295*fb1b10abSAndroid Build Coastguard Worker static double highbd_ssim2(const uint8_t *img1, const uint8_t *img2,
296*fb1b10abSAndroid Build Coastguard Worker int stride_img1, int stride_img2, int width,
297*fb1b10abSAndroid Build Coastguard Worker int height, uint32_t bd) {
298*fb1b10abSAndroid Build Coastguard Worker int i, j;
299*fb1b10abSAndroid Build Coastguard Worker int samples = 0;
300*fb1b10abSAndroid Build Coastguard Worker double ssim_total = 0;
301*fb1b10abSAndroid Build Coastguard Worker
302*fb1b10abSAndroid Build Coastguard Worker // sample point start with each 4x4 location
303*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i <= height - 8;
304*fb1b10abSAndroid Build Coastguard Worker i += 4, img1 += stride_img1 * 4, img2 += stride_img2 * 4) {
305*fb1b10abSAndroid Build Coastguard Worker for (j = 0; j <= width - 8; j += 4) {
306*fb1b10abSAndroid Build Coastguard Worker double v =
307*fb1b10abSAndroid Build Coastguard Worker highbd_ssim_8x8(CONVERT_TO_SHORTPTR(img1 + j), stride_img1,
308*fb1b10abSAndroid Build Coastguard Worker CONVERT_TO_SHORTPTR(img2 + j), stride_img2, bd);
309*fb1b10abSAndroid Build Coastguard Worker ssim_total += v;
310*fb1b10abSAndroid Build Coastguard Worker samples++;
311*fb1b10abSAndroid Build Coastguard Worker }
312*fb1b10abSAndroid Build Coastguard Worker }
313*fb1b10abSAndroid Build Coastguard Worker ssim_total /= samples;
314*fb1b10abSAndroid Build Coastguard Worker return ssim_total;
315*fb1b10abSAndroid Build Coastguard Worker }
316*fb1b10abSAndroid Build Coastguard Worker #endif // CONFIG_VP9_HIGHBITDEPTH
317*fb1b10abSAndroid Build Coastguard Worker
main(int argc,char * argv[])318*fb1b10abSAndroid Build Coastguard Worker int main(int argc, char *argv[]) {
319*fb1b10abSAndroid Build Coastguard Worker FILE *framestats = NULL;
320*fb1b10abSAndroid Build Coastguard Worker int bit_depth = 8;
321*fb1b10abSAndroid Build Coastguard Worker int w = 0, h = 0, tl_skip = 0, tl_skips_remaining = 0;
322*fb1b10abSAndroid Build Coastguard Worker double ssimavg = 0, ssimyavg = 0, ssimuavg = 0, ssimvavg = 0;
323*fb1b10abSAndroid Build Coastguard Worker double psnrglb = 0, psnryglb = 0, psnruglb = 0, psnrvglb = 0;
324*fb1b10abSAndroid Build Coastguard Worker double psnravg = 0, psnryavg = 0, psnruavg = 0, psnrvavg = 0;
325*fb1b10abSAndroid Build Coastguard Worker double *ssimy = NULL, *ssimu = NULL, *ssimv = NULL;
326*fb1b10abSAndroid Build Coastguard Worker uint64_t *psnry = NULL, *psnru = NULL, *psnrv = NULL;
327*fb1b10abSAndroid Build Coastguard Worker size_t i, n_frames = 0, allocated_frames = 0;
328*fb1b10abSAndroid Build Coastguard Worker int return_value = 0;
329*fb1b10abSAndroid Build Coastguard Worker input_file_t in[2];
330*fb1b10abSAndroid Build Coastguard Worker double peak = 255.0;
331*fb1b10abSAndroid Build Coastguard Worker
332*fb1b10abSAndroid Build Coastguard Worker memset(in, 0, sizeof(in));
333*fb1b10abSAndroid Build Coastguard Worker
334*fb1b10abSAndroid Build Coastguard Worker if (argc < 3) {
335*fb1b10abSAndroid Build Coastguard Worker fprintf(stderr,
336*fb1b10abSAndroid Build Coastguard Worker "Usage: %s file1.{yuv|y4m} file2.{yuv|y4m}"
337*fb1b10abSAndroid Build Coastguard Worker " [WxH tl_skip={0,1,3} frame_stats_file bits]\n",
338*fb1b10abSAndroid Build Coastguard Worker argv[0]);
339*fb1b10abSAndroid Build Coastguard Worker return 1;
340*fb1b10abSAndroid Build Coastguard Worker }
341*fb1b10abSAndroid Build Coastguard Worker
342*fb1b10abSAndroid Build Coastguard Worker if (argc > 3) {
343*fb1b10abSAndroid Build Coastguard Worker sscanf(argv[3], "%dx%d", &w, &h);
344*fb1b10abSAndroid Build Coastguard Worker }
345*fb1b10abSAndroid Build Coastguard Worker
346*fb1b10abSAndroid Build Coastguard Worker if (argc > 6) {
347*fb1b10abSAndroid Build Coastguard Worker sscanf(argv[6], "%d", &bit_depth);
348*fb1b10abSAndroid Build Coastguard Worker }
349*fb1b10abSAndroid Build Coastguard Worker
350*fb1b10abSAndroid Build Coastguard Worker if (open_input_file(argv[1], &in[0], w, h, bit_depth) < 0) {
351*fb1b10abSAndroid Build Coastguard Worker fprintf(stderr, "File %s can't be opened or parsed!\n", argv[1]);
352*fb1b10abSAndroid Build Coastguard Worker goto clean_up;
353*fb1b10abSAndroid Build Coastguard Worker }
354*fb1b10abSAndroid Build Coastguard Worker
355*fb1b10abSAndroid Build Coastguard Worker if (w == 0 && h == 0) {
356*fb1b10abSAndroid Build Coastguard Worker // If a y4m is the first file and w, h is not set grab from first file.
357*fb1b10abSAndroid Build Coastguard Worker w = in[0].w;
358*fb1b10abSAndroid Build Coastguard Worker h = in[0].h;
359*fb1b10abSAndroid Build Coastguard Worker bit_depth = in[0].bit_depth;
360*fb1b10abSAndroid Build Coastguard Worker }
361*fb1b10abSAndroid Build Coastguard Worker if (bit_depth == 10) peak = 1023.0;
362*fb1b10abSAndroid Build Coastguard Worker
363*fb1b10abSAndroid Build Coastguard Worker if (bit_depth == 12) peak = 4095.0;
364*fb1b10abSAndroid Build Coastguard Worker
365*fb1b10abSAndroid Build Coastguard Worker if (open_input_file(argv[2], &in[1], w, h, bit_depth) < 0) {
366*fb1b10abSAndroid Build Coastguard Worker fprintf(stderr, "File %s can't be opened or parsed!\n", argv[2]);
367*fb1b10abSAndroid Build Coastguard Worker goto clean_up;
368*fb1b10abSAndroid Build Coastguard Worker }
369*fb1b10abSAndroid Build Coastguard Worker
370*fb1b10abSAndroid Build Coastguard Worker if (in[0].w != in[1].w || in[0].h != in[1].h || in[0].w != w ||
371*fb1b10abSAndroid Build Coastguard Worker in[0].h != h || w == 0 || h == 0) {
372*fb1b10abSAndroid Build Coastguard Worker fprintf(stderr,
373*fb1b10abSAndroid Build Coastguard Worker "Failing: Image dimensions don't match or are unspecified!\n");
374*fb1b10abSAndroid Build Coastguard Worker return_value = 1;
375*fb1b10abSAndroid Build Coastguard Worker goto clean_up;
376*fb1b10abSAndroid Build Coastguard Worker }
377*fb1b10abSAndroid Build Coastguard Worker
378*fb1b10abSAndroid Build Coastguard Worker if (in[0].bit_depth != in[1].bit_depth) {
379*fb1b10abSAndroid Build Coastguard Worker fprintf(stderr,
380*fb1b10abSAndroid Build Coastguard Worker "Failing: Image bit depths don't match or are unspecified!\n");
381*fb1b10abSAndroid Build Coastguard Worker return_value = 1;
382*fb1b10abSAndroid Build Coastguard Worker goto clean_up;
383*fb1b10abSAndroid Build Coastguard Worker }
384*fb1b10abSAndroid Build Coastguard Worker
385*fb1b10abSAndroid Build Coastguard Worker bit_depth = in[0].bit_depth;
386*fb1b10abSAndroid Build Coastguard Worker
387*fb1b10abSAndroid Build Coastguard Worker // Number of frames to skip from file1.yuv for every frame used. Normal
388*fb1b10abSAndroid Build Coastguard Worker // values 0, 1 and 3 correspond to TL2, TL1 and TL0 respectively for a 3TL
389*fb1b10abSAndroid Build Coastguard Worker // encoding in mode 10. 7 would be reasonable for comparing TL0 of a 4-layer
390*fb1b10abSAndroid Build Coastguard Worker // encoding.
391*fb1b10abSAndroid Build Coastguard Worker if (argc > 4) {
392*fb1b10abSAndroid Build Coastguard Worker sscanf(argv[4], "%d", &tl_skip);
393*fb1b10abSAndroid Build Coastguard Worker if (argc > 5) {
394*fb1b10abSAndroid Build Coastguard Worker framestats = fopen(argv[5], "w");
395*fb1b10abSAndroid Build Coastguard Worker if (!framestats) {
396*fb1b10abSAndroid Build Coastguard Worker fprintf(stderr, "Could not open \"%s\" for writing: %s\n", argv[5],
397*fb1b10abSAndroid Build Coastguard Worker strerror(errno));
398*fb1b10abSAndroid Build Coastguard Worker return_value = 1;
399*fb1b10abSAndroid Build Coastguard Worker goto clean_up;
400*fb1b10abSAndroid Build Coastguard Worker }
401*fb1b10abSAndroid Build Coastguard Worker }
402*fb1b10abSAndroid Build Coastguard Worker }
403*fb1b10abSAndroid Build Coastguard Worker
404*fb1b10abSAndroid Build Coastguard Worker while (1) {
405*fb1b10abSAndroid Build Coastguard Worker int r1, r2;
406*fb1b10abSAndroid Build Coastguard Worker unsigned char *y[2], *u[2], *v[2];
407*fb1b10abSAndroid Build Coastguard Worker
408*fb1b10abSAndroid Build Coastguard Worker r1 = read_input_file(&in[0], &y[0], &u[0], &v[0], bit_depth);
409*fb1b10abSAndroid Build Coastguard Worker if (r1 == 0) {
410*fb1b10abSAndroid Build Coastguard Worker if (ferror(in[0].file)) {
411*fb1b10abSAndroid Build Coastguard Worker fprintf(stderr, "Failed to read data from '%s'\n", argv[1]);
412*fb1b10abSAndroid Build Coastguard Worker return_value = 1;
413*fb1b10abSAndroid Build Coastguard Worker goto clean_up;
414*fb1b10abSAndroid Build Coastguard Worker }
415*fb1b10abSAndroid Build Coastguard Worker break;
416*fb1b10abSAndroid Build Coastguard Worker }
417*fb1b10abSAndroid Build Coastguard Worker
418*fb1b10abSAndroid Build Coastguard Worker // Reading parts of file1.yuv that were not used in temporal layer.
419*fb1b10abSAndroid Build Coastguard Worker if (tl_skips_remaining > 0) {
420*fb1b10abSAndroid Build Coastguard Worker --tl_skips_remaining;
421*fb1b10abSAndroid Build Coastguard Worker continue;
422*fb1b10abSAndroid Build Coastguard Worker }
423*fb1b10abSAndroid Build Coastguard Worker // Use frame, but skip |tl_skip| after it.
424*fb1b10abSAndroid Build Coastguard Worker tl_skips_remaining = tl_skip;
425*fb1b10abSAndroid Build Coastguard Worker
426*fb1b10abSAndroid Build Coastguard Worker r2 = read_input_file(&in[1], &y[1], &u[1], &v[1], bit_depth);
427*fb1b10abSAndroid Build Coastguard Worker if (r2 == 0) {
428*fb1b10abSAndroid Build Coastguard Worker if (ferror(in[1].file)) {
429*fb1b10abSAndroid Build Coastguard Worker fprintf(stderr, "Failed to read data from '%s'\n", argv[2]);
430*fb1b10abSAndroid Build Coastguard Worker return_value = 1;
431*fb1b10abSAndroid Build Coastguard Worker goto clean_up;
432*fb1b10abSAndroid Build Coastguard Worker }
433*fb1b10abSAndroid Build Coastguard Worker break;
434*fb1b10abSAndroid Build Coastguard Worker }
435*fb1b10abSAndroid Build Coastguard Worker
436*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
437*fb1b10abSAndroid Build Coastguard Worker #define psnr_and_ssim(ssim, psnr, buf0, buf1, w, h) \
438*fb1b10abSAndroid Build Coastguard Worker do { \
439*fb1b10abSAndroid Build Coastguard Worker if (bit_depth < 9) { \
440*fb1b10abSAndroid Build Coastguard Worker ssim = ssim2(buf0, buf1, w, w, w, h); \
441*fb1b10abSAndroid Build Coastguard Worker psnr = calc_plane_error(buf0, w, buf1, w, w, h); \
442*fb1b10abSAndroid Build Coastguard Worker } else { \
443*fb1b10abSAndroid Build Coastguard Worker ssim = highbd_ssim2(CONVERT_TO_BYTEPTR(buf0), CONVERT_TO_BYTEPTR(buf1), \
444*fb1b10abSAndroid Build Coastguard Worker w, w, w, h, bit_depth); \
445*fb1b10abSAndroid Build Coastguard Worker psnr = calc_plane_error16(CAST_TO_SHORTPTR(buf0), w, \
446*fb1b10abSAndroid Build Coastguard Worker CAST_TO_SHORTPTR(buf1), w, w, h); \
447*fb1b10abSAndroid Build Coastguard Worker } \
448*fb1b10abSAndroid Build Coastguard Worker } while (0)
449*fb1b10abSAndroid Build Coastguard Worker #else
450*fb1b10abSAndroid Build Coastguard Worker #define psnr_and_ssim(ssim, psnr, buf0, buf1, w, h) \
451*fb1b10abSAndroid Build Coastguard Worker do { \
452*fb1b10abSAndroid Build Coastguard Worker ssim = ssim2(buf0, buf1, w, w, w, h); \
453*fb1b10abSAndroid Build Coastguard Worker psnr = calc_plane_error(buf0, w, buf1, w, w, h); \
454*fb1b10abSAndroid Build Coastguard Worker } while (0)
455*fb1b10abSAndroid Build Coastguard Worker #endif // CONFIG_VP9_HIGHBITDEPTH
456*fb1b10abSAndroid Build Coastguard Worker
457*fb1b10abSAndroid Build Coastguard Worker if (n_frames == allocated_frames) {
458*fb1b10abSAndroid Build Coastguard Worker allocated_frames = allocated_frames == 0 ? 1024 : allocated_frames * 2;
459*fb1b10abSAndroid Build Coastguard Worker ssimy = realloc(ssimy, allocated_frames * sizeof(*ssimy));
460*fb1b10abSAndroid Build Coastguard Worker ssimu = realloc(ssimu, allocated_frames * sizeof(*ssimu));
461*fb1b10abSAndroid Build Coastguard Worker ssimv = realloc(ssimv, allocated_frames * sizeof(*ssimv));
462*fb1b10abSAndroid Build Coastguard Worker psnry = realloc(psnry, allocated_frames * sizeof(*psnry));
463*fb1b10abSAndroid Build Coastguard Worker psnru = realloc(psnru, allocated_frames * sizeof(*psnru));
464*fb1b10abSAndroid Build Coastguard Worker psnrv = realloc(psnrv, allocated_frames * sizeof(*psnrv));
465*fb1b10abSAndroid Build Coastguard Worker if (!(ssimy && ssimu && ssimv && psnry && psnru && psnrv)) {
466*fb1b10abSAndroid Build Coastguard Worker fprintf(stderr, "Error allocating SSIM/PSNR data.\n");
467*fb1b10abSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
468*fb1b10abSAndroid Build Coastguard Worker }
469*fb1b10abSAndroid Build Coastguard Worker }
470*fb1b10abSAndroid Build Coastguard Worker psnr_and_ssim(ssimy[n_frames], psnry[n_frames], y[0], y[1], w, h);
471*fb1b10abSAndroid Build Coastguard Worker psnr_and_ssim(ssimu[n_frames], psnru[n_frames], u[0], u[1], (w + 1) / 2,
472*fb1b10abSAndroid Build Coastguard Worker (h + 1) / 2);
473*fb1b10abSAndroid Build Coastguard Worker psnr_and_ssim(ssimv[n_frames], psnrv[n_frames], v[0], v[1], (w + 1) / 2,
474*fb1b10abSAndroid Build Coastguard Worker (h + 1) / 2);
475*fb1b10abSAndroid Build Coastguard Worker
476*fb1b10abSAndroid Build Coastguard Worker n_frames++;
477*fb1b10abSAndroid Build Coastguard Worker }
478*fb1b10abSAndroid Build Coastguard Worker
479*fb1b10abSAndroid Build Coastguard Worker if (framestats) {
480*fb1b10abSAndroid Build Coastguard Worker fprintf(framestats,
481*fb1b10abSAndroid Build Coastguard Worker "ssim,ssim-y,ssim-u,ssim-v,psnr,psnr-y,psnr-u,psnr-v\n");
482*fb1b10abSAndroid Build Coastguard Worker }
483*fb1b10abSAndroid Build Coastguard Worker
484*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < n_frames; ++i) {
485*fb1b10abSAndroid Build Coastguard Worker double frame_ssim;
486*fb1b10abSAndroid Build Coastguard Worker double frame_psnr, frame_psnry, frame_psnru, frame_psnrv;
487*fb1b10abSAndroid Build Coastguard Worker
488*fb1b10abSAndroid Build Coastguard Worker frame_ssim = 0.8 * ssimy[i] + 0.1 * (ssimu[i] + ssimv[i]);
489*fb1b10abSAndroid Build Coastguard Worker ssimavg += frame_ssim;
490*fb1b10abSAndroid Build Coastguard Worker ssimyavg += ssimy[i];
491*fb1b10abSAndroid Build Coastguard Worker ssimuavg += ssimu[i];
492*fb1b10abSAndroid Build Coastguard Worker ssimvavg += ssimv[i];
493*fb1b10abSAndroid Build Coastguard Worker
494*fb1b10abSAndroid Build Coastguard Worker frame_psnr =
495*fb1b10abSAndroid Build Coastguard Worker mse2psnr(w * h * 6 / 4, peak, (double)psnry[i] + psnru[i] + psnrv[i]);
496*fb1b10abSAndroid Build Coastguard Worker frame_psnry = mse2psnr(w * h * 4 / 4, peak, (double)psnry[i]);
497*fb1b10abSAndroid Build Coastguard Worker frame_psnru = mse2psnr(w * h * 1 / 4, peak, (double)psnru[i]);
498*fb1b10abSAndroid Build Coastguard Worker frame_psnrv = mse2psnr(w * h * 1 / 4, peak, (double)psnrv[i]);
499*fb1b10abSAndroid Build Coastguard Worker
500*fb1b10abSAndroid Build Coastguard Worker psnravg += frame_psnr;
501*fb1b10abSAndroid Build Coastguard Worker psnryavg += frame_psnry;
502*fb1b10abSAndroid Build Coastguard Worker psnruavg += frame_psnru;
503*fb1b10abSAndroid Build Coastguard Worker psnrvavg += frame_psnrv;
504*fb1b10abSAndroid Build Coastguard Worker
505*fb1b10abSAndroid Build Coastguard Worker psnryglb += psnry[i];
506*fb1b10abSAndroid Build Coastguard Worker psnruglb += psnru[i];
507*fb1b10abSAndroid Build Coastguard Worker psnrvglb += psnrv[i];
508*fb1b10abSAndroid Build Coastguard Worker
509*fb1b10abSAndroid Build Coastguard Worker if (framestats) {
510*fb1b10abSAndroid Build Coastguard Worker fprintf(framestats, "%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf\n", frame_ssim,
511*fb1b10abSAndroid Build Coastguard Worker ssimy[i], ssimu[i], ssimv[i], frame_psnr, frame_psnry,
512*fb1b10abSAndroid Build Coastguard Worker frame_psnru, frame_psnrv);
513*fb1b10abSAndroid Build Coastguard Worker }
514*fb1b10abSAndroid Build Coastguard Worker }
515*fb1b10abSAndroid Build Coastguard Worker
516*fb1b10abSAndroid Build Coastguard Worker ssimavg /= n_frames;
517*fb1b10abSAndroid Build Coastguard Worker ssimyavg /= n_frames;
518*fb1b10abSAndroid Build Coastguard Worker ssimuavg /= n_frames;
519*fb1b10abSAndroid Build Coastguard Worker ssimvavg /= n_frames;
520*fb1b10abSAndroid Build Coastguard Worker
521*fb1b10abSAndroid Build Coastguard Worker printf("VpxSSIM: %lf\n", 100 * pow(ssimavg, 8.0));
522*fb1b10abSAndroid Build Coastguard Worker printf("SSIM: %lf\n", ssimavg);
523*fb1b10abSAndroid Build Coastguard Worker printf("SSIM-Y: %lf\n", ssimyavg);
524*fb1b10abSAndroid Build Coastguard Worker printf("SSIM-U: %lf\n", ssimuavg);
525*fb1b10abSAndroid Build Coastguard Worker printf("SSIM-V: %lf\n", ssimvavg);
526*fb1b10abSAndroid Build Coastguard Worker puts("");
527*fb1b10abSAndroid Build Coastguard Worker
528*fb1b10abSAndroid Build Coastguard Worker psnravg /= n_frames;
529*fb1b10abSAndroid Build Coastguard Worker psnryavg /= n_frames;
530*fb1b10abSAndroid Build Coastguard Worker psnruavg /= n_frames;
531*fb1b10abSAndroid Build Coastguard Worker psnrvavg /= n_frames;
532*fb1b10abSAndroid Build Coastguard Worker
533*fb1b10abSAndroid Build Coastguard Worker printf("AvgPSNR: %lf\n", psnravg);
534*fb1b10abSAndroid Build Coastguard Worker printf("AvgPSNR-Y: %lf\n", psnryavg);
535*fb1b10abSAndroid Build Coastguard Worker printf("AvgPSNR-U: %lf\n", psnruavg);
536*fb1b10abSAndroid Build Coastguard Worker printf("AvgPSNR-V: %lf\n", psnrvavg);
537*fb1b10abSAndroid Build Coastguard Worker puts("");
538*fb1b10abSAndroid Build Coastguard Worker
539*fb1b10abSAndroid Build Coastguard Worker psnrglb = psnryglb + psnruglb + psnrvglb;
540*fb1b10abSAndroid Build Coastguard Worker psnrglb = mse2psnr((double)n_frames * w * h * 6 / 4, peak, psnrglb);
541*fb1b10abSAndroid Build Coastguard Worker psnryglb = mse2psnr((double)n_frames * w * h * 4 / 4, peak, psnryglb);
542*fb1b10abSAndroid Build Coastguard Worker psnruglb = mse2psnr((double)n_frames * w * h * 1 / 4, peak, psnruglb);
543*fb1b10abSAndroid Build Coastguard Worker psnrvglb = mse2psnr((double)n_frames * w * h * 1 / 4, peak, psnrvglb);
544*fb1b10abSAndroid Build Coastguard Worker
545*fb1b10abSAndroid Build Coastguard Worker printf("GlbPSNR: %lf\n", psnrglb);
546*fb1b10abSAndroid Build Coastguard Worker printf("GlbPSNR-Y: %lf\n", psnryglb);
547*fb1b10abSAndroid Build Coastguard Worker printf("GlbPSNR-U: %lf\n", psnruglb);
548*fb1b10abSAndroid Build Coastguard Worker printf("GlbPSNR-V: %lf\n", psnrvglb);
549*fb1b10abSAndroid Build Coastguard Worker puts("");
550*fb1b10abSAndroid Build Coastguard Worker
551*fb1b10abSAndroid Build Coastguard Worker printf("Nframes: %d\n", (int)n_frames);
552*fb1b10abSAndroid Build Coastguard Worker
553*fb1b10abSAndroid Build Coastguard Worker clean_up:
554*fb1b10abSAndroid Build Coastguard Worker
555*fb1b10abSAndroid Build Coastguard Worker close_input_file(&in[0]);
556*fb1b10abSAndroid Build Coastguard Worker close_input_file(&in[1]);
557*fb1b10abSAndroid Build Coastguard Worker
558*fb1b10abSAndroid Build Coastguard Worker if (framestats) fclose(framestats);
559*fb1b10abSAndroid Build Coastguard Worker
560*fb1b10abSAndroid Build Coastguard Worker free(ssimy);
561*fb1b10abSAndroid Build Coastguard Worker free(ssimu);
562*fb1b10abSAndroid Build Coastguard Worker free(ssimv);
563*fb1b10abSAndroid Build Coastguard Worker
564*fb1b10abSAndroid Build Coastguard Worker free(psnry);
565*fb1b10abSAndroid Build Coastguard Worker free(psnru);
566*fb1b10abSAndroid Build Coastguard Worker free(psnrv);
567*fb1b10abSAndroid Build Coastguard Worker
568*fb1b10abSAndroid Build Coastguard Worker return return_value;
569*fb1b10abSAndroid Build Coastguard Worker }
570