summaryrefslogtreecommitdiff
path: root/media/libaom/src/aom_dsp/psnrhvs.c
diff options
context:
space:
mode:
Diffstat (limited to 'media/libaom/src/aom_dsp/psnrhvs.c')
-rw-r--r--media/libaom/src/aom_dsp/psnrhvs.c121
1 files changed, 63 insertions, 58 deletions
diff --git a/media/libaom/src/aom_dsp/psnrhvs.c b/media/libaom/src/aom_dsp/psnrhvs.c
index 30fe21d9ce..69a1d99bf2 100644
--- a/media/libaom/src/aom_dsp/psnrhvs.c
+++ b/media/libaom/src/aom_dsp/psnrhvs.c
@@ -102,13 +102,8 @@ static const double csf_cr420[8][8] = {
0.478717061273, 0.393021669543, 0.330555063063, 0.285345396658 }
};
-static double convert_score_db(double _score, double _weight, int bit_depth) {
- int16_t pix_max = 255;
+static double convert_score_db(double _score, double _weight, int16_t pix_max) {
assert(_score * _weight >= 0.0);
- if (bit_depth == 10)
- pix_max = 1023;
- else if (bit_depth == 12)
- pix_max = 4095;
if (_weight * _score < pix_max * pix_max * 1e-10) return MAX_PSNR;
return 10 * (log10(pix_max * pix_max) - log10(_weight * _score));
@@ -117,7 +112,8 @@ static double convert_score_db(double _score, double _weight, int bit_depth) {
static double 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 _shift, int buf_is_hbd) {
+ uint32_t _shift, int buf_is_hbd, int16_t pix_max,
+ int luma) {
double ret;
const uint8_t *_src8 = src;
const uint8_t *_dst8 = dst;
@@ -131,8 +127,24 @@ static double calc_psnrhvs(const unsigned char *src, int _systride,
int pixels;
int x;
int y;
+ float sum1;
+ float sum2;
+ float delt;
(void)_par;
ret = pixels = 0;
+ sum1 = sum2 = delt = 0.0f;
+ for (y = 0; y < _h; y++) {
+ for (x = 0; x < _w; x++) {
+ if (!buf_is_hbd) {
+ sum1 += _src8[y * _systride + x];
+ sum2 += _dst8[y * _dystride + x];
+ } else {
+ sum1 += _src16[y * _systride + x] >> _shift;
+ sum2 += _dst16[y * _dystride + x] >> _shift;
+ }
+ }
+ }
+ if (luma) delt = (sum1 - sum2) / (_w * _h);
/*In the PSNR-HVS-M paper[1] the authors describe the construction of
their masking table as "we have used the quantization table for the
color component Y of JPEG [6] that has been also obtained on the
@@ -140,7 +152,7 @@ static double calc_psnrhvs(const unsigned char *src, int _systride,
been normalized and then squared." Their CSF matrix (from PSNR-HVS)
was also constructed from the JPEG matrices. I can not find any obvious
scheme of normalizing to produce their table, but if I multiply their
- CSF by 0.38857 and square the result I get their masking table.
+ CSF by 0.3885746225901003 and square the result I get their masking table.
I have no idea where this constant comes from, but deviating from it
too greatly hurts MOS agreement.
@@ -148,30 +160,28 @@ static double calc_psnrhvs(const unsigned char *src, int _systride,
Jaakko Astola, Vladimir Lukin, "On between-coefficient contrast masking
of DCT basis functions", CD-ROM Proceedings of the Third
International Workshop on Video Processing and Quality Metrics for Consumer
- Electronics VPQM-07, Scottsdale, Arizona, USA, 25-26 January, 2007, 4 p.*/
+ Electronics VPQM-07, Scottsdale, Arizona, USA, 25-26 January, 2007, 4 p.
+
+ Suggested in aomedia issue#2363:
+ 0.3885746225901003 is a reciprocal of the maximum coefficient (2.573509)
+ of the old JPEG based matrix from the paper. Since you are not using that,
+ divide by actual maximum coefficient. */
for (x = 0; x < 8; x++)
for (y = 0; y < 8; y++)
- mask[x][y] =
- (_csf[x][y] * 0.3885746225901003) * (_csf[x][y] * 0.3885746225901003);
+ mask[x][y] = (_csf[x][y] / _csf[1][0]) * (_csf[x][y] / _csf[1][0]);
for (y = 0; y < _h - 7; y += _step) {
for (x = 0; x < _w - 7; x += _step) {
int i;
int j;
- double s_means[4];
- double d_means[4];
- double s_vars[4];
- double d_vars[4];
+ int n = 0;
+ double s_gx = 0;
+ double s_gy = 0;
+ double g = 0;
double s_gmean = 0;
- double d_gmean = 0;
double s_gvar = 0;
- double d_gvar = 0;
double s_mask = 0;
- double d_mask = 0;
- for (i = 0; i < 4; i++)
- s_means[i] = d_means[i] = s_vars[i] = d_vars[i] = 0;
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
- int sub = ((i & 12) >> 2) + ((j & 12) >> 1);
if (!buf_is_hbd) {
dct_s[i * 8 + j] = _src8[(y + i) * _systride + (j + x)];
dct_d[i * 8 + j] = _dst8[(y + i) * _dystride + (j + x)];
@@ -179,35 +189,27 @@ static double calc_psnrhvs(const unsigned char *src, int _systride,
dct_s[i * 8 + j] = _src16[(y + i) * _systride + (j + x)] >> _shift;
dct_d[i * 8 + j] = _dst16[(y + i) * _dystride + (j + x)] >> _shift;
}
- s_gmean += dct_s[i * 8 + j];
- d_gmean += dct_d[i * 8 + j];
- s_means[sub] += dct_s[i * 8 + j];
- d_means[sub] += dct_d[i * 8 + j];
+ dct_d[i * 8 + j] += (int)(delt + 0.5f);
}
}
- s_gmean /= 64.f;
- d_gmean /= 64.f;
- for (i = 0; i < 4; i++) s_means[i] /= 16.f;
- for (i = 0; i < 4; i++) d_means[i] /= 16.f;
- for (i = 0; i < 8; i++) {
- for (j = 0; j < 8; j++) {
- int sub = ((i & 12) >> 2) + ((j & 12) >> 1);
- s_gvar += (dct_s[i * 8 + j] - s_gmean) * (dct_s[i * 8 + j] - s_gmean);
- d_gvar += (dct_d[i * 8 + j] - d_gmean) * (dct_d[i * 8 + j] - d_gmean);
- s_vars[sub] += (dct_s[i * 8 + j] - s_means[sub]) *
- (dct_s[i * 8 + j] - s_means[sub]);
- d_vars[sub] += (dct_d[i * 8 + j] - d_means[sub]) *
- (dct_d[i * 8 + j] - d_means[sub]);
+ for (i = 1; i < 7; i++) {
+ for (j = 1; j < 7; j++) {
+ s_gx = (dct_s[(i - 1) * 8 + j - 1] * 3 -
+ dct_s[(i - 1) * 8 + j + 1] * 3 + dct_s[i * 8 + j - 1] * 10 -
+ dct_s[i * 8 + j + 1] * 10 + dct_s[(i + 1) * 8 + j - 1] * 3 -
+ dct_s[(i + 1) * 8 + j + 1] * 3) /
+ (pix_max * 16.f);
+ s_gy = (dct_s[(i - 1) * 8 + j - 1] * 3 -
+ dct_s[(i + 1) * 8 + j - 1] * 3 + dct_s[(i - 1) * 8 + j] * 10 -
+ dct_s[(i + 1) * 8 + j] * 10 + dct_s[(i - 1) * 8 + j + 1] * 3 -
+ dct_s[(i + 1) * 8 + j + 1] * 3) /
+ (pix_max * 16.f);
+ g = sqrt(s_gx * s_gx + s_gy * s_gy);
+ if (g > 0.1f) n++;
+ s_gmean += g;
}
}
- s_gvar *= 1 / 63.f * 64;
- d_gvar *= 1 / 63.f * 64;
- for (i = 0; i < 4; i++) s_vars[i] *= 1 / 15.f * 16;
- for (i = 0; i < 4; i++) d_vars[i] *= 1 / 15.f * 16;
- if (s_gvar > 0)
- s_gvar = (s_vars[0] + s_vars[1] + s_vars[2] + s_vars[3]) / s_gvar;
- if (d_gvar > 0)
- d_gvar = (d_vars[0] + d_vars[1] + d_vars[2] + d_vars[3]) / d_gvar;
+ s_gvar = 1.f / (36 - n + 1) * s_gmean / 36.f;
if (!buf_is_hbd) {
od_bin_fdct8x8(dct_s_coef, 8, dct_s, 8);
od_bin_fdct8x8(dct_d_coef, 8, dct_d, 8);
@@ -218,12 +220,7 @@ static double calc_psnrhvs(const unsigned char *src, int _systride,
for (i = 0; i < 8; i++)
for (j = (i == 0); j < 8; j++)
s_mask += dct_s_coef[i * 8 + j] * dct_s_coef[i * 8 + j] * mask[i][j];
- for (i = 0; i < 8; i++)
- for (j = (i == 0); j < 8; j++)
- d_mask += dct_d_coef[i * 8 + j] * dct_d_coef[i * 8 + j] * mask[i][j];
- s_mask = sqrt(s_mask * s_gvar) / 32.f;
- d_mask = sqrt(d_mask * d_gvar) / 32.f;
- if (d_mask > s_mask) s_mask = d_mask;
+ s_mask = sqrt(s_mask * s_gvar) / 8.f;
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
double err;
@@ -238,6 +235,7 @@ static double calc_psnrhvs(const unsigned char *src, int _systride,
}
if (pixels <= 0) return 0;
ret /= pixels;
+ ret += 0.04 * delt * delt;
return ret;
}
@@ -254,19 +252,26 @@ double aom_psnrhvs(const YV12_BUFFER_CONFIG *src, const YV12_BUFFER_CONFIG *dst,
assert(src->flags == dst->flags);
const int buf_is_hbd = src->flags & YV12_FLAG_HIGHBITDEPTH;
+ int16_t pix_max = 255;
+ if (in_bd == 10)
+ pix_max = 1023;
+ else if (in_bd == 12)
+ pix_max = 4095;
+
bd_shift = bd - in_bd;
- *y_psnrhvs = calc_psnrhvs(
- src->y_buffer, src->y_stride, dst->y_buffer, dst->y_stride, par,
- src->y_crop_width, src->y_crop_height, step, csf_y, bd_shift, buf_is_hbd);
+ *y_psnrhvs =
+ calc_psnrhvs(src->y_buffer, src->y_stride, dst->y_buffer, dst->y_stride,
+ par, src->y_crop_width, src->y_crop_height, step, csf_y,
+ bd_shift, buf_is_hbd, pix_max, 1);
*u_psnrhvs =
calc_psnrhvs(src->u_buffer, src->uv_stride, dst->u_buffer, dst->uv_stride,
par, src->uv_crop_width, src->uv_crop_height, step,
- csf_cb420, bd_shift, buf_is_hbd);
+ csf_cb420, bd_shift, buf_is_hbd, pix_max, 0);
*v_psnrhvs =
calc_psnrhvs(src->v_buffer, src->uv_stride, dst->v_buffer, dst->uv_stride,
par, src->uv_crop_width, src->uv_crop_height, step,
- csf_cr420, bd_shift, buf_is_hbd);
+ csf_cr420, bd_shift, buf_is_hbd, pix_max, 0);
psnrhvs = (*y_psnrhvs) * .8 + .1 * ((*u_psnrhvs) + (*v_psnrhvs));
- return convert_score_db(psnrhvs, 1.0, in_bd);
+ return convert_score_db(psnrhvs, 1.0, pix_max);
}