1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker * Copyright (c) 2010 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 * This code was originally written by: Gregory Maxwell, at the Daala
11*fb1b10abSAndroid Build Coastguard Worker * project.
12*fb1b10abSAndroid Build Coastguard Worker */
13*fb1b10abSAndroid Build Coastguard Worker #include <assert.h>
14*fb1b10abSAndroid Build Coastguard Worker #include <stdio.h>
15*fb1b10abSAndroid Build Coastguard Worker #include <stdlib.h>
16*fb1b10abSAndroid Build Coastguard Worker #include <math.h>
17*fb1b10abSAndroid Build Coastguard Worker
18*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_config.h"
19*fb1b10abSAndroid Build Coastguard Worker #include "./vpx_dsp_rtcd.h"
20*fb1b10abSAndroid Build Coastguard Worker #include "vpx_dsp/ssim.h"
21*fb1b10abSAndroid Build Coastguard Worker #include "vpx_ports/system_state.h"
22*fb1b10abSAndroid Build Coastguard Worker #include "vpx_dsp/psnr.h"
23*fb1b10abSAndroid Build Coastguard Worker
24*fb1b10abSAndroid Build Coastguard Worker #if !defined(M_PI)
25*fb1b10abSAndroid Build Coastguard Worker #define M_PI (3.141592653589793238462643)
26*fb1b10abSAndroid Build Coastguard Worker #endif
27*fb1b10abSAndroid Build Coastguard Worker #include <string.h>
28*fb1b10abSAndroid Build Coastguard Worker
od_bin_fdct8x8(tran_low_t * y,int ystride,const int16_t * x,int xstride)29*fb1b10abSAndroid Build Coastguard Worker static void od_bin_fdct8x8(tran_low_t *y, int ystride, const int16_t *x,
30*fb1b10abSAndroid Build Coastguard Worker int xstride) {
31*fb1b10abSAndroid Build Coastguard Worker int i, j;
32*fb1b10abSAndroid Build Coastguard Worker (void)xstride;
33*fb1b10abSAndroid Build Coastguard Worker vpx_fdct8x8(x, y, ystride);
34*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < 8; i++)
35*fb1b10abSAndroid Build Coastguard Worker for (j = 0; j < 8; j++)
36*fb1b10abSAndroid Build Coastguard Worker *(y + ystride * i + j) = (*(y + ystride * i + j) + 4) >> 3;
37*fb1b10abSAndroid Build Coastguard Worker }
38*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
hbd_od_bin_fdct8x8(tran_low_t * y,int ystride,const int16_t * x,int xstride)39*fb1b10abSAndroid Build Coastguard Worker static void hbd_od_bin_fdct8x8(tran_low_t *y, int ystride, const int16_t *x,
40*fb1b10abSAndroid Build Coastguard Worker int xstride) {
41*fb1b10abSAndroid Build Coastguard Worker int i, j;
42*fb1b10abSAndroid Build Coastguard Worker (void)xstride;
43*fb1b10abSAndroid Build Coastguard Worker vpx_highbd_fdct8x8(x, y, ystride);
44*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < 8; i++)
45*fb1b10abSAndroid Build Coastguard Worker for (j = 0; j < 8; j++)
46*fb1b10abSAndroid Build Coastguard Worker *(y + ystride * i + j) = (*(y + ystride * i + j) + 4) >> 3;
47*fb1b10abSAndroid Build Coastguard Worker }
48*fb1b10abSAndroid Build Coastguard Worker #endif
49*fb1b10abSAndroid Build Coastguard Worker
50*fb1b10abSAndroid Build Coastguard Worker /* Normalized inverse quantization matrix for 8x8 DCT at the point of
51*fb1b10abSAndroid Build Coastguard Worker * transparency. This is not the JPEG based matrix from the paper,
52*fb1b10abSAndroid Build Coastguard Worker this one gives a slightly higher MOS agreement.*/
53*fb1b10abSAndroid Build Coastguard Worker static const double csf_y[8][8] = {
54*fb1b10abSAndroid Build Coastguard Worker { 1.6193873005, 2.2901594831, 2.08509755623, 1.48366094411, 1.00227514334,
55*fb1b10abSAndroid Build Coastguard Worker 0.678296995242, 0.466224900598, 0.3265091542 },
56*fb1b10abSAndroid Build Coastguard Worker { 2.2901594831, 1.94321815382, 2.04793073064, 1.68731108984, 1.2305666963,
57*fb1b10abSAndroid Build Coastguard Worker 0.868920337363, 0.61280991668, 0.436405793551 },
58*fb1b10abSAndroid Build Coastguard Worker { 2.08509755623, 2.04793073064, 1.34329019223, 1.09205635862, 0.875748795257,
59*fb1b10abSAndroid Build Coastguard Worker 0.670882927016, 0.501731932449, 0.372504254596 },
60*fb1b10abSAndroid Build Coastguard Worker { 1.48366094411, 1.68731108984, 1.09205635862, 0.772819797575, 0.605636379554,
61*fb1b10abSAndroid Build Coastguard Worker 0.48309405692, 0.380429446972, 0.295774038565 },
62*fb1b10abSAndroid Build Coastguard Worker { 1.00227514334, 1.2305666963, 0.875748795257, 0.605636379554, 0.448996256676,
63*fb1b10abSAndroid Build Coastguard Worker 0.352889268808, 0.283006984131, 0.226951348204 },
64*fb1b10abSAndroid Build Coastguard Worker { 0.678296995242, 0.868920337363, 0.670882927016, 0.48309405692,
65*fb1b10abSAndroid Build Coastguard Worker 0.352889268808, 0.27032073436, 0.215017739696, 0.17408067321 },
66*fb1b10abSAndroid Build Coastguard Worker { 0.466224900598, 0.61280991668, 0.501731932449, 0.380429446972,
67*fb1b10abSAndroid Build Coastguard Worker 0.283006984131, 0.215017739696, 0.168869545842, 0.136153931001 },
68*fb1b10abSAndroid Build Coastguard Worker { 0.3265091542, 0.436405793551, 0.372504254596, 0.295774038565,
69*fb1b10abSAndroid Build Coastguard Worker 0.226951348204, 0.17408067321, 0.136153931001, 0.109083846276 }
70*fb1b10abSAndroid Build Coastguard Worker };
71*fb1b10abSAndroid Build Coastguard Worker static const double csf_cb420[8][8] = {
72*fb1b10abSAndroid Build Coastguard Worker { 1.91113096927, 2.46074210438, 1.18284184739, 1.14982565193, 1.05017074788,
73*fb1b10abSAndroid Build Coastguard Worker 0.898018824055, 0.74725392039, 0.615105596242 },
74*fb1b10abSAndroid Build Coastguard Worker { 2.46074210438, 1.58529308355, 1.21363250036, 1.38190029285, 1.33100189972,
75*fb1b10abSAndroid Build Coastguard Worker 1.17428548929, 0.996404342439, 0.830890433625 },
76*fb1b10abSAndroid Build Coastguard Worker { 1.18284184739, 1.21363250036, 0.978712413627, 1.02624506078, 1.03145147362,
77*fb1b10abSAndroid Build Coastguard Worker 0.960060382087, 0.849823426169, 0.731221236837 },
78*fb1b10abSAndroid Build Coastguard Worker { 1.14982565193, 1.38190029285, 1.02624506078, 0.861317501629, 0.801821139099,
79*fb1b10abSAndroid Build Coastguard Worker 0.751437590932, 0.685398513368, 0.608694761374 },
80*fb1b10abSAndroid Build Coastguard Worker { 1.05017074788, 1.33100189972, 1.03145147362, 0.801821139099, 0.676555426187,
81*fb1b10abSAndroid Build Coastguard Worker 0.605503172737, 0.55002013668, 0.495804539034 },
82*fb1b10abSAndroid Build Coastguard Worker { 0.898018824055, 1.17428548929, 0.960060382087, 0.751437590932,
83*fb1b10abSAndroid Build Coastguard Worker 0.605503172737, 0.514674450957, 0.454353482512, 0.407050308965 },
84*fb1b10abSAndroid Build Coastguard Worker { 0.74725392039, 0.996404342439, 0.849823426169, 0.685398513368,
85*fb1b10abSAndroid Build Coastguard Worker 0.55002013668, 0.454353482512, 0.389234902883, 0.342353999733 },
86*fb1b10abSAndroid Build Coastguard Worker { 0.615105596242, 0.830890433625, 0.731221236837, 0.608694761374,
87*fb1b10abSAndroid Build Coastguard Worker 0.495804539034, 0.407050308965, 0.342353999733, 0.295530605237 }
88*fb1b10abSAndroid Build Coastguard Worker };
89*fb1b10abSAndroid Build Coastguard Worker static const double csf_cr420[8][8] = {
90*fb1b10abSAndroid Build Coastguard Worker { 2.03871978502, 2.62502345193, 1.26180942886, 1.11019789803, 1.01397751469,
91*fb1b10abSAndroid Build Coastguard Worker 0.867069376285, 0.721500455585, 0.593906509971 },
92*fb1b10abSAndroid Build Coastguard Worker { 2.62502345193, 1.69112867013, 1.17180569821, 1.3342742857, 1.28513006198,
93*fb1b10abSAndroid Build Coastguard Worker 1.13381474809, 0.962064122248, 0.802254508198 },
94*fb1b10abSAndroid Build Coastguard Worker { 1.26180942886, 1.17180569821, 0.944981930573, 0.990876405848,
95*fb1b10abSAndroid Build Coastguard Worker 0.995903384143, 0.926972725286, 0.820534991409, 0.706020324706 },
96*fb1b10abSAndroid Build Coastguard Worker { 1.11019789803, 1.3342742857, 0.990876405848, 0.831632933426, 0.77418706195,
97*fb1b10abSAndroid Build Coastguard Worker 0.725539939514, 0.661776842059, 0.587716619023 },
98*fb1b10abSAndroid Build Coastguard Worker { 1.01397751469, 1.28513006198, 0.995903384143, 0.77418706195, 0.653238524286,
99*fb1b10abSAndroid Build Coastguard Worker 0.584635025748, 0.531064164893, 0.478717061273 },
100*fb1b10abSAndroid Build Coastguard Worker { 0.867069376285, 1.13381474809, 0.926972725286, 0.725539939514,
101*fb1b10abSAndroid Build Coastguard Worker 0.584635025748, 0.496936637883, 0.438694579826, 0.393021669543 },
102*fb1b10abSAndroid Build Coastguard Worker { 0.721500455585, 0.962064122248, 0.820534991409, 0.661776842059,
103*fb1b10abSAndroid Build Coastguard Worker 0.531064164893, 0.438694579826, 0.375820256136, 0.330555063063 },
104*fb1b10abSAndroid Build Coastguard Worker { 0.593906509971, 0.802254508198, 0.706020324706, 0.587716619023,
105*fb1b10abSAndroid Build Coastguard Worker 0.478717061273, 0.393021669543, 0.330555063063, 0.285345396658 }
106*fb1b10abSAndroid Build Coastguard Worker };
107*fb1b10abSAndroid Build Coastguard Worker
convert_score_db(double _score,double _weight,int bit_depth)108*fb1b10abSAndroid Build Coastguard Worker static double convert_score_db(double _score, double _weight, int bit_depth) {
109*fb1b10abSAndroid Build Coastguard Worker int16_t pix_max = 255;
110*fb1b10abSAndroid Build Coastguard Worker assert(_score * _weight >= 0.0);
111*fb1b10abSAndroid Build Coastguard Worker if (bit_depth == 10)
112*fb1b10abSAndroid Build Coastguard Worker pix_max = 1023;
113*fb1b10abSAndroid Build Coastguard Worker else if (bit_depth == 12)
114*fb1b10abSAndroid Build Coastguard Worker pix_max = 4095;
115*fb1b10abSAndroid Build Coastguard Worker
116*fb1b10abSAndroid Build Coastguard Worker if (_weight * _score < pix_max * pix_max * 1e-10) return MAX_PSNR;
117*fb1b10abSAndroid Build Coastguard Worker return 10 * (log10(pix_max * pix_max) - log10(_weight * _score));
118*fb1b10abSAndroid Build Coastguard Worker }
119*fb1b10abSAndroid Build Coastguard Worker
calc_psnrhvs(const unsigned char * src,int _systride,const unsigned char * dst,int _dystride,double _par,int _w,int _h,int _step,const double _csf[8][8],uint32_t bit_depth,uint32_t _shift)120*fb1b10abSAndroid Build Coastguard Worker static double calc_psnrhvs(const unsigned char *src, int _systride,
121*fb1b10abSAndroid Build Coastguard Worker const unsigned char *dst, int _dystride, double _par,
122*fb1b10abSAndroid Build Coastguard Worker int _w, int _h, int _step, const double _csf[8][8],
123*fb1b10abSAndroid Build Coastguard Worker uint32_t bit_depth, uint32_t _shift) {
124*fb1b10abSAndroid Build Coastguard Worker double ret;
125*fb1b10abSAndroid Build Coastguard Worker const uint8_t *_src8 = src;
126*fb1b10abSAndroid Build Coastguard Worker const uint8_t *_dst8 = dst;
127*fb1b10abSAndroid Build Coastguard Worker const uint16_t *_src16 = CONVERT_TO_SHORTPTR(src);
128*fb1b10abSAndroid Build Coastguard Worker const uint16_t *_dst16 = CONVERT_TO_SHORTPTR(dst);
129*fb1b10abSAndroid Build Coastguard Worker DECLARE_ALIGNED(16, int16_t, dct_s[8 * 8]);
130*fb1b10abSAndroid Build Coastguard Worker DECLARE_ALIGNED(16, int16_t, dct_d[8 * 8]);
131*fb1b10abSAndroid Build Coastguard Worker DECLARE_ALIGNED(16, tran_low_t, dct_s_coef[8 * 8]);
132*fb1b10abSAndroid Build Coastguard Worker DECLARE_ALIGNED(16, tran_low_t, dct_d_coef[8 * 8]);
133*fb1b10abSAndroid Build Coastguard Worker double mask[8][8];
134*fb1b10abSAndroid Build Coastguard Worker int pixels;
135*fb1b10abSAndroid Build Coastguard Worker int x;
136*fb1b10abSAndroid Build Coastguard Worker int y;
137*fb1b10abSAndroid Build Coastguard Worker (void)_par;
138*fb1b10abSAndroid Build Coastguard Worker ret = pixels = 0;
139*fb1b10abSAndroid Build Coastguard Worker
140*fb1b10abSAndroid Build Coastguard Worker /*In the PSNR-HVS-M paper[1] the authors describe the construction of
141*fb1b10abSAndroid Build Coastguard Worker their masking table as "we have used the quantization table for the
142*fb1b10abSAndroid Build Coastguard Worker color component Y of JPEG [6] that has been also obtained on the
143*fb1b10abSAndroid Build Coastguard Worker basis of CSF. Note that the values in quantization table JPEG have
144*fb1b10abSAndroid Build Coastguard Worker been normalized and then squared." Their CSF matrix (from PSNR-HVS)
145*fb1b10abSAndroid Build Coastguard Worker was also constructed from the JPEG matrices. I can not find any obvious
146*fb1b10abSAndroid Build Coastguard Worker scheme of normalizing to produce their table, but if I multiply their
147*fb1b10abSAndroid Build Coastguard Worker CSF by 0.3885746225901003 and square the result I get their masking table.
148*fb1b10abSAndroid Build Coastguard Worker I have no idea where this constant comes from, but deviating from it
149*fb1b10abSAndroid Build Coastguard Worker too greatly hurts MOS agreement.
150*fb1b10abSAndroid Build Coastguard Worker
151*fb1b10abSAndroid Build Coastguard Worker [1] Nikolay Ponomarenko, Flavia Silvestri, Karen Egiazarian, Marco Carli,
152*fb1b10abSAndroid Build Coastguard Worker Jaakko Astola, Vladimir Lukin, "On between-coefficient contrast masking
153*fb1b10abSAndroid Build Coastguard Worker of DCT basis functions", CD-ROM Proceedings of the Third
154*fb1b10abSAndroid Build Coastguard Worker International Workshop on Video Processing and Quality Metrics for Consumer
155*fb1b10abSAndroid Build Coastguard Worker Electronics VPQM-07, Scottsdale, Arizona, USA, 25-26 January, 2007, 4 p.
156*fb1b10abSAndroid Build Coastguard Worker
157*fb1b10abSAndroid Build Coastguard Worker Suggested in aomedia issue #2363:
158*fb1b10abSAndroid Build Coastguard Worker 0.3885746225901003 is a reciprocal of the maximum coefficient (2.573509)
159*fb1b10abSAndroid Build Coastguard Worker of the old JPEG based matrix from the paper. Since you are not using that,
160*fb1b10abSAndroid Build Coastguard Worker divide by actual maximum coefficient. */
161*fb1b10abSAndroid Build Coastguard Worker for (x = 0; x < 8; x++)
162*fb1b10abSAndroid Build Coastguard Worker for (y = 0; y < 8; y++)
163*fb1b10abSAndroid Build Coastguard Worker mask[x][y] = (_csf[x][y] / _csf[1][0]) * (_csf[x][y] / _csf[1][0]);
164*fb1b10abSAndroid Build Coastguard Worker for (y = 0; y < _h - 7; y += _step) {
165*fb1b10abSAndroid Build Coastguard Worker for (x = 0; x < _w - 7; x += _step) {
166*fb1b10abSAndroid Build Coastguard Worker int i;
167*fb1b10abSAndroid Build Coastguard Worker int j;
168*fb1b10abSAndroid Build Coastguard Worker double s_means[4];
169*fb1b10abSAndroid Build Coastguard Worker double d_means[4];
170*fb1b10abSAndroid Build Coastguard Worker double s_vars[4];
171*fb1b10abSAndroid Build Coastguard Worker double d_vars[4];
172*fb1b10abSAndroid Build Coastguard Worker double s_gmean = 0;
173*fb1b10abSAndroid Build Coastguard Worker double d_gmean = 0;
174*fb1b10abSAndroid Build Coastguard Worker double s_gvar = 0;
175*fb1b10abSAndroid Build Coastguard Worker double d_gvar = 0;
176*fb1b10abSAndroid Build Coastguard Worker double s_mask = 0;
177*fb1b10abSAndroid Build Coastguard Worker double d_mask = 0;
178*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < 4; i++)
179*fb1b10abSAndroid Build Coastguard Worker s_means[i] = d_means[i] = s_vars[i] = d_vars[i] = 0;
180*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
181*fb1b10abSAndroid Build Coastguard Worker for (j = 0; j < 8; j++) {
182*fb1b10abSAndroid Build Coastguard Worker int sub = ((i & 12) >> 2) + ((j & 12) >> 1);
183*fb1b10abSAndroid Build Coastguard Worker if (bit_depth == 8 && _shift == 0) {
184*fb1b10abSAndroid Build Coastguard Worker dct_s[i * 8 + j] = _src8[(y + i) * _systride + (j + x)];
185*fb1b10abSAndroid Build Coastguard Worker dct_d[i * 8 + j] = _dst8[(y + i) * _dystride + (j + x)];
186*fb1b10abSAndroid Build Coastguard Worker } else if (bit_depth == 10 || bit_depth == 12) {
187*fb1b10abSAndroid Build Coastguard Worker dct_s[i * 8 + j] = _src16[(y + i) * _systride + (j + x)] >> _shift;
188*fb1b10abSAndroid Build Coastguard Worker dct_d[i * 8 + j] = _dst16[(y + i) * _dystride + (j + x)] >> _shift;
189*fb1b10abSAndroid Build Coastguard Worker }
190*fb1b10abSAndroid Build Coastguard Worker s_gmean += dct_s[i * 8 + j];
191*fb1b10abSAndroid Build Coastguard Worker d_gmean += dct_d[i * 8 + j];
192*fb1b10abSAndroid Build Coastguard Worker s_means[sub] += dct_s[i * 8 + j];
193*fb1b10abSAndroid Build Coastguard Worker d_means[sub] += dct_d[i * 8 + j];
194*fb1b10abSAndroid Build Coastguard Worker }
195*fb1b10abSAndroid Build Coastguard Worker }
196*fb1b10abSAndroid Build Coastguard Worker s_gmean /= 64.f;
197*fb1b10abSAndroid Build Coastguard Worker d_gmean /= 64.f;
198*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < 4; i++) s_means[i] /= 16.f;
199*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < 4; i++) d_means[i] /= 16.f;
200*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
201*fb1b10abSAndroid Build Coastguard Worker for (j = 0; j < 8; j++) {
202*fb1b10abSAndroid Build Coastguard Worker int sub = ((i & 12) >> 2) + ((j & 12) >> 1);
203*fb1b10abSAndroid Build Coastguard Worker s_gvar += (dct_s[i * 8 + j] - s_gmean) * (dct_s[i * 8 + j] - s_gmean);
204*fb1b10abSAndroid Build Coastguard Worker d_gvar += (dct_d[i * 8 + j] - d_gmean) * (dct_d[i * 8 + j] - d_gmean);
205*fb1b10abSAndroid Build Coastguard Worker s_vars[sub] += (dct_s[i * 8 + j] - s_means[sub]) *
206*fb1b10abSAndroid Build Coastguard Worker (dct_s[i * 8 + j] - s_means[sub]);
207*fb1b10abSAndroid Build Coastguard Worker d_vars[sub] += (dct_d[i * 8 + j] - d_means[sub]) *
208*fb1b10abSAndroid Build Coastguard Worker (dct_d[i * 8 + j] - d_means[sub]);
209*fb1b10abSAndroid Build Coastguard Worker }
210*fb1b10abSAndroid Build Coastguard Worker }
211*fb1b10abSAndroid Build Coastguard Worker s_gvar *= 1 / 63.f * 64;
212*fb1b10abSAndroid Build Coastguard Worker d_gvar *= 1 / 63.f * 64;
213*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < 4; i++) s_vars[i] *= 1 / 15.f * 16;
214*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < 4; i++) d_vars[i] *= 1 / 15.f * 16;
215*fb1b10abSAndroid Build Coastguard Worker if (s_gvar > 0)
216*fb1b10abSAndroid Build Coastguard Worker s_gvar = (s_vars[0] + s_vars[1] + s_vars[2] + s_vars[3]) / s_gvar;
217*fb1b10abSAndroid Build Coastguard Worker if (d_gvar > 0)
218*fb1b10abSAndroid Build Coastguard Worker d_gvar = (d_vars[0] + d_vars[1] + d_vars[2] + d_vars[3]) / d_gvar;
219*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
220*fb1b10abSAndroid Build Coastguard Worker if (bit_depth == 10 || bit_depth == 12) {
221*fb1b10abSAndroid Build Coastguard Worker hbd_od_bin_fdct8x8(dct_s_coef, 8, dct_s, 8);
222*fb1b10abSAndroid Build Coastguard Worker hbd_od_bin_fdct8x8(dct_d_coef, 8, dct_d, 8);
223*fb1b10abSAndroid Build Coastguard Worker }
224*fb1b10abSAndroid Build Coastguard Worker #endif
225*fb1b10abSAndroid Build Coastguard Worker if (bit_depth == 8) {
226*fb1b10abSAndroid Build Coastguard Worker od_bin_fdct8x8(dct_s_coef, 8, dct_s, 8);
227*fb1b10abSAndroid Build Coastguard Worker od_bin_fdct8x8(dct_d_coef, 8, dct_d, 8);
228*fb1b10abSAndroid Build Coastguard Worker }
229*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < 8; i++)
230*fb1b10abSAndroid Build Coastguard Worker for (j = (i == 0); j < 8; j++)
231*fb1b10abSAndroid Build Coastguard Worker s_mask += dct_s_coef[i * 8 + j] * dct_s_coef[i * 8 + j] * mask[i][j];
232*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < 8; i++)
233*fb1b10abSAndroid Build Coastguard Worker for (j = (i == 0); j < 8; j++)
234*fb1b10abSAndroid Build Coastguard Worker d_mask += dct_d_coef[i * 8 + j] * dct_d_coef[i * 8 + j] * mask[i][j];
235*fb1b10abSAndroid Build Coastguard Worker s_mask = sqrt(s_mask * s_gvar) / 32.f;
236*fb1b10abSAndroid Build Coastguard Worker d_mask = sqrt(d_mask * d_gvar) / 32.f;
237*fb1b10abSAndroid Build Coastguard Worker if (d_mask > s_mask) s_mask = d_mask;
238*fb1b10abSAndroid Build Coastguard Worker for (i = 0; i < 8; i++) {
239*fb1b10abSAndroid Build Coastguard Worker for (j = 0; j < 8; j++) {
240*fb1b10abSAndroid Build Coastguard Worker double err;
241*fb1b10abSAndroid Build Coastguard Worker err = fabs((double)(dct_s_coef[i * 8 + j] - dct_d_coef[i * 8 + j]));
242*fb1b10abSAndroid Build Coastguard Worker if (i != 0 || j != 0)
243*fb1b10abSAndroid Build Coastguard Worker err = err < s_mask / mask[i][j] ? 0 : err - s_mask / mask[i][j];
244*fb1b10abSAndroid Build Coastguard Worker ret += (err * _csf[i][j]) * (err * _csf[i][j]);
245*fb1b10abSAndroid Build Coastguard Worker pixels++;
246*fb1b10abSAndroid Build Coastguard Worker }
247*fb1b10abSAndroid Build Coastguard Worker }
248*fb1b10abSAndroid Build Coastguard Worker }
249*fb1b10abSAndroid Build Coastguard Worker }
250*fb1b10abSAndroid Build Coastguard Worker if (pixels <= 0) return 0;
251*fb1b10abSAndroid Build Coastguard Worker ret /= pixels;
252*fb1b10abSAndroid Build Coastguard Worker return ret;
253*fb1b10abSAndroid Build Coastguard Worker }
254*fb1b10abSAndroid Build Coastguard Worker
vpx_psnrhvs(const YV12_BUFFER_CONFIG * src,const YV12_BUFFER_CONFIG * dest,double * y_psnrhvs,double * u_psnrhvs,double * v_psnrhvs,uint32_t bd,uint32_t in_bd)255*fb1b10abSAndroid Build Coastguard Worker double vpx_psnrhvs(const YV12_BUFFER_CONFIG *src,
256*fb1b10abSAndroid Build Coastguard Worker const YV12_BUFFER_CONFIG *dest, double *y_psnrhvs,
257*fb1b10abSAndroid Build Coastguard Worker double *u_psnrhvs, double *v_psnrhvs, uint32_t bd,
258*fb1b10abSAndroid Build Coastguard Worker uint32_t in_bd) {
259*fb1b10abSAndroid Build Coastguard Worker double psnrhvs;
260*fb1b10abSAndroid Build Coastguard Worker const double par = 1.0;
261*fb1b10abSAndroid Build Coastguard Worker const int step = 7;
262*fb1b10abSAndroid Build Coastguard Worker uint32_t bd_shift = 0;
263*fb1b10abSAndroid Build Coastguard Worker vpx_clear_system_state();
264*fb1b10abSAndroid Build Coastguard Worker
265*fb1b10abSAndroid Build Coastguard Worker assert(bd == 8 || bd == 10 || bd == 12);
266*fb1b10abSAndroid Build Coastguard Worker assert(bd >= in_bd);
267*fb1b10abSAndroid Build Coastguard Worker
268*fb1b10abSAndroid Build Coastguard Worker bd_shift = bd - in_bd;
269*fb1b10abSAndroid Build Coastguard Worker
270*fb1b10abSAndroid Build Coastguard Worker *y_psnrhvs = calc_psnrhvs(src->y_buffer, src->y_stride, dest->y_buffer,
271*fb1b10abSAndroid Build Coastguard Worker dest->y_stride, par, src->y_crop_width,
272*fb1b10abSAndroid Build Coastguard Worker src->y_crop_height, step, csf_y, bd, bd_shift);
273*fb1b10abSAndroid Build Coastguard Worker *u_psnrhvs = calc_psnrhvs(src->u_buffer, src->uv_stride, dest->u_buffer,
274*fb1b10abSAndroid Build Coastguard Worker dest->uv_stride, par, src->uv_crop_width,
275*fb1b10abSAndroid Build Coastguard Worker src->uv_crop_height, step, csf_cb420, bd, bd_shift);
276*fb1b10abSAndroid Build Coastguard Worker *v_psnrhvs = calc_psnrhvs(src->v_buffer, src->uv_stride, dest->v_buffer,
277*fb1b10abSAndroid Build Coastguard Worker dest->uv_stride, par, src->uv_crop_width,
278*fb1b10abSAndroid Build Coastguard Worker src->uv_crop_height, step, csf_cr420, bd, bd_shift);
279*fb1b10abSAndroid Build Coastguard Worker psnrhvs = (*y_psnrhvs) * .8 + .1 * ((*u_psnrhvs) + (*v_psnrhvs));
280*fb1b10abSAndroid Build Coastguard Worker return convert_score_db(psnrhvs, 1.0, in_bd);
281*fb1b10abSAndroid Build Coastguard Worker }
282