Commit 89a1ab39 authored by Yaowu Xu's avatar Yaowu Xu Committed by Gerrit Code Review

Merge "Enable computing PSNRHVS for hbd build" into nextgenv2

parents c1924b9f bb8ca088
......@@ -32,6 +32,22 @@ typedef double (*HBDMetricFunc)(const YV12_BUFFER_CONFIG *source,
const YV12_BUFFER_CONFIG *dest,
uint32_t bd);
double compute_hbd_psnrhvs(const YV12_BUFFER_CONFIG *source,
const YV12_BUFFER_CONFIG *dest,
uint32_t bit_depth) {
double tempy, tempu, tempv;
return vpx_psnrhvs(source, dest,
&tempy, &tempu, &tempv, bit_depth);
}
double compute_psnrhvs(const YV12_BUFFER_CONFIG *source,
const YV12_BUFFER_CONFIG *dest) {
double tempy, tempu, tempv;
return vpx_psnrhvs(source, dest,
&tempy, &tempu, &tempv, 8);
}
double compute_hbd_fastssim(const YV12_BUFFER_CONFIG *source,
const YV12_BUFFER_CONFIG *dest,
uint32_t bit_depth) {
......@@ -62,6 +78,7 @@ double compute_vpxssim(const YV12_BUFFER_CONFIG *source,
return 100 * pow(ssim / weight, 8.0);
}
class HBDMetricsTestBase {
public:
virtual ~HBDMetricsTestBase() {}
......@@ -101,16 +118,40 @@ class HBDMetricsTestBase {
lbd_db = lbd_metric_(&lbd_src, &lbd_dst);
hbd_db = hbd_metric_(&hbd_src, &hbd_dst, bit_depth_);
EXPECT_LE(fabs(lbd_db - hbd_db), threshold_);
i = 0;
while (i < lbd_src.buffer_alloc_sz) {
uint16_t dpel;
// Create some small distortion for dst buffer.
dpel = 120 + (rnd.Rand8() >> 4);
lbd_dst.buffer_alloc[i] = (uint8_t)dpel;
((uint16_t*)(hbd_dst.buffer_alloc))[i] = dpel << (bit_depth_ - 8);
i++;
}
lbd_db = lbd_metric_(&lbd_src, &lbd_dst);
hbd_db = hbd_metric_(&hbd_src, &hbd_dst, bit_depth_);
EXPECT_LE(fabs(lbd_db - hbd_db), threshold_);
printf("%10f \n", lbd_db);
printf("%10f \n", hbd_db);
i = 0;
while (i < lbd_src.buffer_alloc_sz) {
uint16_t dpel;
// Create some small distortion for dst buffer.
dpel = 126 + (rnd.Rand8() >> 6);
lbd_dst.buffer_alloc[i] = (uint8_t)dpel;
((uint16_t*)(hbd_dst.buffer_alloc))[i] = dpel << (bit_depth_ - 8);
i++;
}
lbd_db = lbd_metric_(&lbd_src, &lbd_dst);
hbd_db = hbd_metric_(&hbd_src, &hbd_dst, bit_depth_);
EXPECT_LE(fabs(lbd_db - hbd_db), threshold_);
vpx_free_frame_buffer(&lbd_src);
vpx_free_frame_buffer(&lbd_dst);
vpx_free_frame_buffer(&hbd_src);
vpx_free_frame_buffer(&hbd_dst);
EXPECT_LE(fabs(lbd_db - hbd_db), threshold_);
}
int bit_depth_;
......@@ -140,8 +181,10 @@ TEST_P(HBDMetricsTest, RunAccuracyCheck) {
// Allow small variation due to floating point operations.
static const double kSsim_thresh = 0.001;
// Allow some variation from accumulated errors in floating point operations.
static const double kFSsim_thresh = 0.01;
// Allow some additional errors accumulated in floating point operations.
static const double kFSsim_thresh = 0.03;
// Allow some extra variation due to rounding error accumulated in dct.
static const double kPhvs_thresh = 0.3;
INSTANTIATE_TEST_CASE_P(
VPXSSIM, HBDMetricsTest,
......@@ -157,5 +200,13 @@ INSTANTIATE_TEST_CASE_P(
kFSsim_thresh),
MetricTestTParam(&compute_fastssim, &compute_hbd_fastssim, 12,
kFSsim_thresh)));
INSTANTIATE_TEST_CASE_P(
PSNRHVS, HBDMetricsTest,
::testing::Values(
MetricTestTParam(&compute_psnrhvs, &compute_hbd_psnrhvs, 10,
kPhvs_thresh),
MetricTestTParam(&compute_psnrhvs, &compute_hbd_psnrhvs, 12,
kPhvs_thresh)));
} // namespace
......@@ -4509,13 +4509,7 @@ int vp10_get_compressed_data(VP10_COMP *cpi, unsigned int *frame_flags,
double y, u, v, frame_all;
frame_all = vpx_calc_fastssim(orig, recon, &y, &u, &v, bit_depth);
adjust_image_stat(y, u, v, frame_all, &cpi->fastssim);
}
#if CONFIG_VP9_HIGHBITDEPTH
if (!cm->use_highbitdepth)
#endif
{
double y, u, v, frame_all;
frame_all = vpx_psnrhvs(orig, recon, &y, &u, &v);
frame_all = vpx_psnrhvs(orig, recon, &y, &u, &v, bit_depth);
adjust_image_stat(y, u, v, frame_all, &cpi->psnrhvs);
}
}
......
......@@ -4681,12 +4681,10 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
&v, bit_depth);
adjust_image_stat(y, u, v, frame_all, &cpi->fastssim);
}
#if CONFIG_VP9_HIGHBITDEPTH
if (!cm->use_highbitdepth)
#endif
{
double y, u, v, frame_all;
frame_all = vpx_psnrhvs(cpi->Source, cm->frame_to_show, &y, &u, &v);
frame_all = vpx_psnrhvs(cpi->Source, cm->frame_to_show, &y, &u, &v,
bit_depth);
adjust_image_stat(y, u, v, frame_all, &cpi->psnrhvs);
}
}
......
......@@ -506,8 +506,6 @@ static double calc_ssim(const unsigned char *_src, int _systride,
}
#define CONVERT_TO_SHORTPTR(x) ((uint16_t*)(((uintptr_t)(x)) << 1))
static double calc_hbd_ssim(const uint8_t *_src, int _systride,
const uint8_t *_dst, int _dystride,
int _w, int _h, uint32_t bit_depth) {
......
......@@ -35,6 +35,17 @@ static void od_bin_fdct8x8(tran_low_t *y, int ystride, const int16_t *x,
for (j = 0; j< 8; j++)
*(y + ystride*i + j) = (*(y + ystride*i + j) + 4) >> 3;
}
#if CONFIG_VP9_HIGHBITDEPTH
static void hbd_od_bin_fdct8x8(tran_low_t *y, int ystride, const int16_t *x,
int xstride) {
int i, j;
(void) xstride;
vpx_highbd_fdct8x8(x, y, ystride);
for (i = 0; i < 8; i++)
for (j = 0; j< 8; j++)
*(y + ystride*i + j) = (*(y + ystride*i + j) + 4) >> 3;
}
#endif
/* Normalized inverse quantization matrix for 8x8 DCT at the point of
* transparency. This is not the JPEG based matrix from the paper,
......@@ -91,18 +102,28 @@ static const double csf_cr420[8][8] = {
{0.593906509971, 0.802254508198, 0.706020324706, 0.587716619023,
0.478717061273, 0.393021669543, 0.330555063063, 0.285345396658}};
static double convert_score_db(double _score, double _weight) {
static double convert_score_db(double _score, double _weight, int bit_depth) {
int16_t pix_max = 255;
assert(_score * _weight >= 0.0);
if (_weight * _score < 255 * 255 * 1e-10)
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(255 * 255) - log10(_weight * _score));
return 10 * (log10(pix_max * pix_max) - log10(_weight * _score));
}
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]) {
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 bit_depth) {
double ret;
const uint8_t *_src8 = src;
const uint8_t *_dst8 = dst;
const uint16_t *_src16 = CONVERT_TO_SHORTPTR(src);
const uint16_t *_dst16 = CONVERT_TO_SHORTPTR(dst);
int16_t dct_s[8 * 8], dct_d[8 * 8];
tran_low_t dct_s_coef[8 * 8], dct_d_coef[8 * 8];
double mask[8][8];
......@@ -111,6 +132,7 @@ static double calc_psnrhvs(const unsigned char *_src, int _systride,
int y;
(void) _par;
ret = pixels = 0;
/*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
......@@ -150,8 +172,13 @@ static double calc_psnrhvs(const unsigned char *_src, int _systride,
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
int sub = ((i & 12) >> 2) + ((j & 12) >> 1);
dct_s[i * 8 + j] = _src[(y + i) * _systride + (j + x)];
dct_d[i * 8 + j] = _dst[(y + i) * _dystride + (j + x)];
if (bit_depth == 8) {
dct_s[i * 8 + j] = _src8[(y + i) * _systride + (j + x)];
dct_d[i * 8 + j] = _dst8[(y + i) * _dystride + (j + x)];
} else if (bit_depth == 10 || bit_depth == 12) {
dct_s[i * 8 + j] = _src16[(y + i) * _systride + (j + x)];
dct_d[i * 8 + j] = _dst16[(y + i) * _dystride + (j + x)];
}
s_gmean += dct_s[i * 8 + j];
d_gmean += dct_d[i * 8 + j];
s_means[sub] += dct_s[i * 8 + j];
......@@ -185,8 +212,16 @@ static double calc_psnrhvs(const unsigned char *_src, int _systride,
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;
od_bin_fdct8x8(dct_s_coef, 8, dct_s, 8);
od_bin_fdct8x8(dct_d_coef, 8, dct_d, 8);
#if CONFIG_VP9_HIGHBITDEPTH
if (bit_depth == 10 || bit_depth == 12) {
hbd_od_bin_fdct8x8(dct_s_coef, 8, dct_s, 8);
hbd_od_bin_fdct8x8(dct_d_coef, 8, dct_d, 8);
}
#endif
if (bit_depth == 8) {
od_bin_fdct8x8(dct_s_coef, 8, dct_s, 8);
od_bin_fdct8x8(dct_d_coef, 8, dct_d, 8);
}
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];
......@@ -200,7 +235,7 @@ static double calc_psnrhvs(const unsigned char *_src, int _systride,
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
double err;
err = fabs((float)(dct_s_coef[i * 8 + j] - dct_d_coef[i * 8 + j]));
err = fabs((double)(dct_s_coef[i * 8 + j] - dct_d_coef[i * 8 + j]));
if (i != 0 || j != 0)
err = err < s_mask / mask[i][j] ? 0 : err - s_mask / mask[i][j];
ret += (err * _csf[i][j]) * (err * _csf[i][j]);
......@@ -212,25 +247,28 @@ static double calc_psnrhvs(const unsigned char *_src, int _systride,
ret /= pixels;
return ret;
}
double vpx_psnrhvs(const YV12_BUFFER_CONFIG *source,
const YV12_BUFFER_CONFIG *dest, double *y_psnrhvs,
double *u_psnrhvs, double *v_psnrhvs) {
double *u_psnrhvs, double *v_psnrhvs, uint32_t bit_depth) {
double psnrhvs;
const double par = 1.0;
const int step = 7;
vpx_clear_system_state();
assert(bit_depth == 8 || bit_depth == 10 || bit_depth == 12);
*y_psnrhvs = calc_psnrhvs(source->y_buffer, source->y_stride, dest->y_buffer,
dest->y_stride, par, source->y_crop_width,
source->y_crop_height, step, csf_y);
source->y_crop_height, step, csf_y, bit_depth);
*u_psnrhvs = calc_psnrhvs(source->u_buffer, source->uv_stride, dest->u_buffer,
dest->uv_stride, par, source->uv_crop_width,
source->uv_crop_height, step, csf_cb420);
source->uv_crop_height, step, csf_cb420, bit_depth);
*v_psnrhvs = calc_psnrhvs(source->v_buffer, source->uv_stride, dest->v_buffer,
dest->uv_stride, par, source->uv_crop_width,
source->uv_crop_height, step, csf_cr420);
source->uv_crop_height, step, csf_cr420, bit_depth);
psnrhvs = (*y_psnrhvs) * .8 + .1 * ((*u_psnrhvs) + (*v_psnrhvs));
return convert_score_db(psnrhvs, 1.0);
return convert_score_db(psnrhvs, 1.0, bit_depth);
}
......@@ -77,7 +77,8 @@ double vpx_calc_fastssim(const YV12_BUFFER_CONFIG *source,
double vpx_psnrhvs(const YV12_BUFFER_CONFIG *source,
const YV12_BUFFER_CONFIG *dest,
double *ssim_y, double *ssim_u, double *ssim_v);
double *phvs_y, double *phvs_u,
double *phvs_v, uint32_t bit_depth);
#if CONFIG_VP9_HIGHBITDEPTH
double vpx_highbd_calc_ssim(const YV12_BUFFER_CONFIG *source,
......
......@@ -45,8 +45,8 @@
#define ALIGN_POWER_OF_TWO(value, n) \
(((value) + ((1 << (n)) - 1)) & ~((1 << (n)) - 1))
#if CONFIG_VP9_HIGHBITDEPTH
#define CONVERT_TO_SHORTPTR(x) ((uint16_t*)(((uintptr_t)(x)) << 1))
#if CONFIG_VP9_HIGHBITDEPTH
#define CONVERT_TO_BYTEPTR(x) ((uint8_t*)(((uintptr_t)(x)) >> 1))
#endif // CONFIG_VP9_HIGHBITDEPTH
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment