Add stream bit-depth based SSIM in internal stat file.
This patch adds support to compute SSIM based on stream bit-depth
when input bit-depth is lower than stream bit-depth.
Change-Id: I820e0ccb6e280f28b8ea66ac78ba4e54bf75a29f
diff --git a/aom_dsp/ssim.c b/aom_dsp/ssim.c
index dd4e0eb..357da99 100644
--- a/aom_dsp/ssim.c
+++ b/aom_dsp/ssim.c
@@ -165,8 +165,9 @@
return ssim_total;
}
-double aom_calc_ssim(const YV12_BUFFER_CONFIG *source,
- const YV12_BUFFER_CONFIG *dest, double *weight) {
+void aom_calc_ssim(const YV12_BUFFER_CONFIG *source,
+ const YV12_BUFFER_CONFIG *dest, double *weight,
+ double *fast_ssim) {
double abc[3];
for (int i = 0; i < 3; ++i) {
const int is_uv = i > 0;
@@ -176,7 +177,7 @@
}
*weight = 1;
- return abc[0] * .8 + .1 * (abc[1] + abc[2]);
+ *fast_ssim = abc[0] * .8 + .1 * (abc[1] + abc[2]);
}
// traditional ssim as per: http://en.wikipedia.org/wiki/Structural_similarity
@@ -421,11 +422,11 @@
return inconsistency_total;
}
-double aom_highbd_calc_ssim(const YV12_BUFFER_CONFIG *source,
- const YV12_BUFFER_CONFIG *dest, double *weight,
- uint32_t bd, uint32_t in_bd) {
+void aom_highbd_calc_ssim(const YV12_BUFFER_CONFIG *source,
+ const YV12_BUFFER_CONFIG *dest, double *weight,
+ uint32_t bd, uint32_t in_bd, double *fast_ssim) {
assert(bd >= in_bd);
- const uint32_t shift = bd - in_bd;
+ uint32_t shift = bd - in_bd;
double abc[3];
for (int i = 0; i < 3; ++i) {
@@ -436,6 +437,21 @@
source->crop_heights[is_uv], in_bd, shift);
}
- *weight = 1;
- return abc[0] * .8 + .1 * (abc[1] + abc[2]);
+ weight[0] = 1;
+ fast_ssim[0] = abc[0] * .8 + .1 * (abc[1] + abc[2]);
+
+ if (bd > in_bd) {
+ // Compute SSIM based on stream bit depth
+ shift = 0;
+ for (int i = 0; i < 3; ++i) {
+ const int is_uv = i > 0;
+ abc[i] = aom_highbd_ssim2(source->buffers[i], dest->buffers[i],
+ source->strides[is_uv], dest->strides[is_uv],
+ source->crop_widths[is_uv],
+ source->crop_heights[is_uv], bd, shift);
+ }
+
+ weight[1] = 1;
+ fast_ssim[1] = abc[0] * .8 + .1 * (abc[1] + abc[2]);
+ }
}
diff --git a/aom_dsp/ssim.h b/aom_dsp/ssim.h
index 55038f4..d635ef5 100644
--- a/aom_dsp/ssim.h
+++ b/aom_dsp/ssim.h
@@ -68,17 +68,18 @@
int img2_pitch, int width, int height, Ssimv *sv2,
Metrics *m, int do_inconsistency);
-double aom_calc_ssim(const YV12_BUFFER_CONFIG *source,
- const YV12_BUFFER_CONFIG *dest, double *weight);
+void aom_calc_ssim(const YV12_BUFFER_CONFIG *source,
+ const YV12_BUFFER_CONFIG *dest, double *weight,
+ double *fast_ssim);
double aom_calc_fastssim(const YV12_BUFFER_CONFIG *source,
const YV12_BUFFER_CONFIG *dest, double *ssim_y,
double *ssim_u, double *ssim_v, uint32_t bd,
uint32_t in_bd);
-double aom_highbd_calc_ssim(const YV12_BUFFER_CONFIG *source,
- const YV12_BUFFER_CONFIG *dest, double *weight,
- uint32_t bd, uint32_t in_bd);
+void aom_highbd_calc_ssim(const YV12_BUFFER_CONFIG *source,
+ const YV12_BUFFER_CONFIG *dest, double *weight,
+ uint32_t bd, uint32_t in_bd, double *fast_ssim);
#ifdef __cplusplus
} // extern "C"
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 5cd06bc..639d914 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -901,6 +901,7 @@
cpi->psnr[0].worst = 100.0;
cpi->psnr[1].worst = 100.0;
cpi->worst_ssim = 100.0;
+ cpi->worst_ssim_hbd = 100.0;
cpi->count[0] = 0;
cpi->count[1] = 0;
@@ -917,6 +918,8 @@
cpi->tot_recode_hits = 0;
cpi->summed_quality = 0;
cpi->summed_weights = 0;
+ cpi->summed_quality_hbd = 0;
+ cpi->summed_weights_hbd = 0;
}
cpi->fastssim.worst = 100.0;
@@ -1448,9 +1451,12 @@
const double total_psnr_hbd =
aom_sse_to_psnr((double)cpi->total_samples[1], peak_hbd,
(double)cpi->total_sq_error[1]);
+ const double total_ssim_hbd =
+ 100 * pow(cpi->summed_quality_hbd / cpi->summed_weights_hbd, 8.0);
SNPRINT(headings,
"\t AVGPsnrH GLBPsnrH AVPsnrPH GLPsnrPH"
- " AVPsnrYH APsnrCbH APsnrCrH WstPsnrH");
+ " AVPsnrYH APsnrCbH APsnrCrH WstPsnrH"
+ " AOMSSIMH VPSSIMPH WstSsimH");
SNPRINT2(results, "\t%7.3f",
cpi->psnr[1].stat[STAT_ALL] / cpi->count[1]);
SNPRINT2(results, " %7.3f", total_psnr_hbd);
@@ -1464,6 +1470,9 @@
SNPRINT2(results, " %7.3f",
cpi->psnr[1].stat[STAT_V] / cpi->count[1]);
SNPRINT2(results, " %7.3f", cpi->psnr[1].worst);
+ SNPRINT2(results, " %7.3f", total_ssim_hbd);
+ SNPRINT2(results, " %7.3f", total_ssim_hbd);
+ SNPRINT2(results, " %7.3f", cpi->worst_ssim_hbd);
}
#endif
fprintf(f, "%s\n", headings);
@@ -3354,7 +3363,8 @@
cpi->count[1]++;
if (cpi->b_calculate_psnr) {
PSNR_STATS psnr;
- double frame_ssim2 = 0.0, weight = 0.0;
+ double weight[2] = { 0.0, 0.0 };
+ double frame_ssim2[2] = { 0.0, 0.0 };
aom_clear_system_state();
#if CONFIG_AV1_HIGHBITDEPTH
aom_calc_highbd_psnr(orig, recon, &psnr, bit_depth, in_bit_depth);
@@ -3369,14 +3379,14 @@
// TODO(yaowu): unify these two versions into one.
if (cm->seq_params.use_highbitdepth)
- frame_ssim2 =
- aom_highbd_calc_ssim(orig, recon, &weight, bit_depth, in_bit_depth);
+ aom_highbd_calc_ssim(orig, recon, weight, bit_depth, in_bit_depth,
+ frame_ssim2);
else
- frame_ssim2 = aom_calc_ssim(orig, recon, &weight);
+ aom_calc_ssim(orig, recon, &weight[0], &frame_ssim2[0]);
- cpi->worst_ssim = AOMMIN(cpi->worst_ssim, frame_ssim2);
- cpi->summed_quality += frame_ssim2 * weight;
- cpi->summed_weights += weight;
+ cpi->worst_ssim = AOMMIN(cpi->worst_ssim, frame_ssim2[0]);
+ cpi->summed_quality += frame_ssim2[0] * weight[0];
+ cpi->summed_weights += weight[0];
#if CONFIG_AV1_HIGHBITDEPTH
// Compute PSNR based on stream bit depth
@@ -3386,6 +3396,10 @@
psnr.psnr_hbd[0], &cpi->psnr[1]);
cpi->total_sq_error[1] += psnr.sse_hbd[0];
cpi->total_samples[1] += psnr.samples_hbd[0];
+
+ cpi->worst_ssim_hbd = AOMMIN(cpi->worst_ssim_hbd, frame_ssim2[1]);
+ cpi->summed_quality_hbd += frame_ssim2[1] * weight[1];
+ cpi->summed_weights_hbd += weight[1];
}
#endif
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 04aab64..84e0dce 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -2244,8 +2244,11 @@
int bytes;
double summed_quality;
double summed_weights;
+ double summed_quality_hbd;
+ double summed_weights_hbd;
unsigned int tot_recode_hits;
double worst_ssim;
+ double worst_ssim_hbd;
ImageStat fastssim;
ImageStat psnrhvs;
diff --git a/test/hbd_metrics_test.cc b/test/hbd_metrics_test.cc
index 5b03bee..8044b51 100644
--- a/test/hbd_metrics_test.cc
+++ b/test/hbd_metrics_test.cc
@@ -80,15 +80,15 @@
double compute_hbd_aomssim(const YV12_BUFFER_CONFIG *source,
const YV12_BUFFER_CONFIG *dest, uint32_t in_bd,
uint32_t bd) {
- double ssim, weight;
- ssim = aom_highbd_calc_ssim(source, dest, &weight, bd, in_bd);
- return 100 * pow(ssim / weight, 8.0);
+ double ssim[2], weight[2];
+ aom_highbd_calc_ssim(source, dest, weight, bd, in_bd, ssim);
+ return 100 * pow(ssim[0] / weight[0], 8.0);
}
double compute_aomssim(const YV12_BUFFER_CONFIG *source,
const YV12_BUFFER_CONFIG *dest) {
double ssim, weight;
- ssim = aom_calc_ssim(source, dest, &weight);
+ aom_calc_ssim(source, dest, &weight, &ssim);
return 100 * pow(ssim / weight, 8.0);
}