Bugfix for encoder reported PSNR for superres. Earlier, encoder PSNR computation was incorrectly comparing scaled source with upscaled encoded frame, so values reported by "--psnr" were incorrect when superres was being used. We change the logic of when scaling is required to correct this problem. Note: only affects output of "--psnr"; no change in encoding output. BUG=aomedia:2844 Change-Id: I40fe1f6a14fbdbbcd60342daf48a39cda6ff1498 (cherry picked from commit 708a34f56356bdbb53a9e725a1421ebdb6e52889)
diff --git a/aom_dsp/psnr.c b/aom_dsp/psnr.c index c66dd52..ddeb96a 100644 --- a/aom_dsp/psnr.c +++ b/aom_dsp/psnr.c
@@ -363,6 +363,10 @@ void aom_calc_highbd_psnr(const YV12_BUFFER_CONFIG *a, const YV12_BUFFER_CONFIG *b, PSNR_STATS *psnr, uint32_t bit_depth, uint32_t in_bit_depth) { + assert(a->y_crop_width == b->y_crop_width); + assert(a->y_crop_height == b->y_crop_height); + assert(a->uv_crop_width == b->uv_crop_width); + assert(a->uv_crop_height == b->uv_crop_height); const int widths[3] = { a->y_crop_width, a->uv_crop_width, a->uv_crop_width }; const int heights[3] = { a->y_crop_height, a->uv_crop_height, a->uv_crop_height }; @@ -408,6 +412,10 @@ void aom_calc_psnr(const YV12_BUFFER_CONFIG *a, const YV12_BUFFER_CONFIG *b, PSNR_STATS *psnr) { + assert(a->y_crop_width == b->y_crop_width); + assert(a->y_crop_height == b->y_crop_height); + assert(a->uv_crop_width == b->uv_crop_width); + assert(a->uv_crop_height == b->uv_crop_height); static const double peak = 255.0; const int widths[3] = { a->y_crop_width, a->uv_crop_width, a->uv_crop_width }; const int heights[3] = { a->y_crop_height, a->uv_crop_height,
diff --git a/av1/common/resize.c b/av1/common/resize.c index 74f6432..65df27b 100644 --- a/av1/common/resize.c +++ b/av1/common/resize.c
@@ -1338,15 +1338,21 @@ aom_extend_frame_borders(dst, num_planes); } -YV12_BUFFER_CONFIG *av1_scale_if_required(AV1_COMMON *cm, - YV12_BUFFER_CONFIG *unscaled, - YV12_BUFFER_CONFIG *scaled, - const InterpFilter filter, - const int phase, - const int use_optimized_scaler) { - const int num_planes = av1_num_planes(cm); - if (cm->width != unscaled->y_crop_width || - cm->height != unscaled->y_crop_height) { +YV12_BUFFER_CONFIG *av1_scale_if_required( + AV1_COMMON *cm, YV12_BUFFER_CONFIG *unscaled, YV12_BUFFER_CONFIG *scaled, + const InterpFilter filter, const int phase, const bool use_optimized_scaler, + const bool for_psnr) { + // If scaling is performed for the sole purpose of calculating PSNR, then our + // target dimensions are superres upscaled width/height. Otherwise our target + // dimensions are coded width/height. + const bool scaling_required = + for_psnr ? (cm->superres_upscaled_width != unscaled->y_crop_width || + cm->superres_upscaled_height != unscaled->y_crop_height) + : (cm->width != unscaled->y_crop_width || + cm->height != unscaled->y_crop_height); + + if (scaling_required) { + const int num_planes = av1_num_planes(cm); #if CONFIG_AV1_HIGHBITDEPTH if (use_optimized_scaler && cm->seq_params.bit_depth == AOM_BITS_8) { av1_resize_and_extend_frame(unscaled, scaled, filter, phase, num_planes);
diff --git a/av1/common/resize.h b/av1/common/resize.h index af6eeb7..b08de80 100644 --- a/av1/common/resize.h +++ b/av1/common/resize.h
@@ -73,7 +73,8 @@ YV12_BUFFER_CONFIG *av1_scale_if_required( AV1_COMMON *cm, YV12_BUFFER_CONFIG *unscaled, YV12_BUFFER_CONFIG *scaled, - const InterpFilter filter, const int phase, const int use_optimized_scaler); + const InterpFilter filter, const int phase, const bool use_optimized_scaler, + const bool for_psnr); void av1_resize_and_extend_frame_nonnormative(const YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst, int bd,
diff --git a/av1/encoder/encode_strategy.c b/av1/encoder/encode_strategy.c index 9c3562a..e30d668 100644 --- a/av1/encoder/encode_strategy.c +++ b/av1/encoder/encode_strategy.c
@@ -1205,8 +1205,9 @@ // Set frame_input source to true source for psnr calculation. if (apply_filtering && is_psnr_calc_enabled(cpi)) { - cpi->source = av1_scale_if_required(cm, source_buffer, &cpi->scaled_source, - cm->features.interp_filter, 0, 0); + cpi->source = + av1_scale_if_required(cm, source_buffer, &cpi->scaled_source, + cm->features.interp_filter, 0, false, true); cpi->unscaled_source = source_buffer; }
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c index e44680a..7286c02 100644 --- a/av1/encoder/encoder.c +++ b/av1/encoder/encoder.c
@@ -2160,7 +2160,7 @@ aom_clear_system_state(); cpi->source = av1_scale_if_required(cm, unscaled, &cpi->scaled_source, - filter_scaler, phase_scaler, 1); + filter_scaler, phase_scaler, true, false); if (frame_is_intra_only(cm) || resize_pending != 0) { memset(cpi->consec_zero_mv, 0, ((cm->mi_params.mi_rows * cm->mi_params.mi_cols) >> 2) * @@ -2168,9 +2168,9 @@ } if (cpi->unscaled_last_source != NULL) { - cpi->last_source = av1_scale_if_required(cm, cpi->unscaled_last_source, - &cpi->scaled_last_source, - filter_scaler, phase_scaler, 1); + cpi->last_source = av1_scale_if_required( + cm, cpi->unscaled_last_source, &cpi->scaled_last_source, filter_scaler, + phase_scaler, true, false); } if (cpi->sf.rt_sf.use_temporal_noise_estimate) { @@ -2364,13 +2364,14 @@ gm_info->search_done = 0; } } - cpi->source = av1_scale_if_required( - cm, cpi->unscaled_source, &cpi->scaled_source, EIGHTTAP_REGULAR, 0, 0); + cpi->source = + av1_scale_if_required(cm, cpi->unscaled_source, &cpi->scaled_source, + EIGHTTAP_REGULAR, 0, false, false); if (cpi->unscaled_last_source != NULL) { - cpi->last_source = av1_scale_if_required(cm, cpi->unscaled_last_source, - &cpi->scaled_last_source, - EIGHTTAP_REGULAR, 0, 0); + cpi->last_source = av1_scale_if_required( + cm, cpi->unscaled_last_source, &cpi->scaled_last_source, + EIGHTTAP_REGULAR, 0, false, false); } if (!frame_is_intra_only(cm)) {
diff --git a/av1/encoder/encoder_utils.c b/av1/encoder/encoder_utils.c index a626af4..0054cf7 100644 --- a/av1/encoder/encoder_utils.c +++ b/av1/encoder/encoder_utils.c
@@ -810,11 +810,11 @@ cpi->source = av1_scale_if_required(cm, cpi->unscaled_source, &cpi->scaled_source, - cm->features.interp_filter, 0, 0); + cm->features.interp_filter, 0, false, false); if (cpi->unscaled_last_source != NULL) { - cpi->last_source = av1_scale_if_required(cm, cpi->unscaled_last_source, - &cpi->scaled_last_source, - cm->features.interp_filter, 0, 0); + cpi->last_source = av1_scale_if_required( + cm, cpi->unscaled_last_source, &cpi->scaled_last_source, + cm->features.interp_filter, 0, false, false); } av1_setup_frame(cpi);