Merge "Enable computing PSNRHVS for hbd build" into nextgenv2
This commit is contained in:
@@ -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_);
|
||||
|
||||
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 = 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_);
|
||||
|
||||
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
|
||||
|
||||
|
Reference in New Issue
Block a user