From 7e234b92286fbf96be601f2ff239a7afe2f6c09b Mon Sep 17 00:00:00 2001 From: paulwilkins Date: Wed, 18 Mar 2015 14:41:18 +0000 Subject: [PATCH] Revised rd adjustment for variance. Revised adjustment for rd based on source complexity. Two cases: 1) Bias against low variance intra predictors when the actual source variance is higher. 2) When the source variance is very low to give a slight bias against predictors that might introduce false texture or features. The impact on metrics of this change across the test sets is small and mixed. derf -0.073%, -0.049%, -0.291% std hd -0.093%, -0.1%, -0.557% yt +0.186%, +0.04%, - 0.074% ythd +0.625%, + 0.563%, +0.584% Medium to strong psycho-visual improvements in some problem clips. This feature and intra weight on GF group length now turned on by default. Change-Id: Idefc8b633a7b7bc56c42dbe19f6b2f872d73851e --- vp9/encoder/vp9_firstpass.c | 15 ++--------- vp9/encoder/vp9_rdopt.c | 50 +++++++++++++++++++++---------------- 2 files changed, 31 insertions(+), 34 deletions(-) diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 3f28e0ff3..b5c3658b3 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -61,12 +61,9 @@ #define RC_FACTOR_MAX 1.75 -#define INTRA_WEIGHT_EXPERIMENT 0 -#if INTRA_WEIGHT_EXPERIMENT #define NCOUNT_INTRA_THRESH 8192 #define NCOUNT_INTRA_FACTOR 3 #define NCOUNT_FRAME_II_THRESH 5.0 -#endif #define DOUBLE_DIVIDE_CHECK(x) ((x) < 0 ? (x) - 0.000001 : (x) + 0.000001) @@ -832,7 +829,6 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) { // Keep a count of cases where the inter and intra were very close // and very low. This helps with scene cut detection for example in // cropped clips with black bars at the sides or top and bottom. -#if INTRA_WEIGHT_EXPERIMENT if (((this_error - intrapenalty) * 9 <= motion_error * 10) && (this_error < (2 * intrapenalty))) { neutral_count += 1.0; @@ -843,12 +839,6 @@ void vp9_first_pass(VP9_COMP *cpi, const struct lookahead_entry *source) { neutral_count += (double)motion_error / DOUBLE_DIVIDE_CHECK((double)this_error); } -#else - if (((this_error - intrapenalty) * 9 <= motion_error * 10) && - (this_error < (2 * intrapenalty))) { - neutral_count += 1.0; - } -#endif mv.row *= 8; mv.col *= 8; @@ -1291,11 +1281,10 @@ static double get_sr_decay_rate(const VP9_COMP *cpi, frame->pcnt_motion * ((frame->mvc_abs + frame->mvr_abs) / 2); modified_pct_inter = frame->pcnt_inter; -#if INTRA_WEIGHT_EXPERIMENT if ((frame->intra_error / DOUBLE_DIVIDE_CHECK(frame->coded_error)) < - (double)NCOUNT_FRAME_II_THRESH) + (double)NCOUNT_FRAME_II_THRESH) { modified_pct_inter = frame->pcnt_inter - frame->pcnt_neutral; -#endif + } modified_pcnt_intra = 100 * (1.0 - modified_pct_inter); diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c index 7dabb7bb5..73902767f 100644 --- a/vp9/encoder/vp9_rdopt.c +++ b/vp9/encoder/vp9_rdopt.c @@ -50,7 +50,6 @@ #define MIN_EARLY_TERM_INDEX 3 #define NEW_MV_DISCOUNT_FACTOR 8 -#define SOURCE_VARIANCE_RD_ADJUSTMENT 0 typedef struct { PREDICTION_MODE mode; @@ -2825,21 +2824,22 @@ void vp9_rd_pick_intra_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, rd_cost->rdcost = RDCOST(x->rdmult, x->rddiv, rd_cost->rate, rd_cost->dist); } -#if SOURCE_VARIANCE_RD_ADJUSTMENT // This function is designed to apply a bias or adjustment to an rd value based // on the relative variance of the source and reconstruction. #define LOW_VAR_THRESH 16 -#define LOW_VAR_DIFF_THRESH 1 #define VLOW_ADJ_MAX 25 -#define VHIGH_ADJ_MAX 10 +#define VHIGH_ADJ_MAX 8 static void rd_variance_adjustment(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize, int64_t *this_rd, + MV_REFERENCE_FRAME ref_frame, unsigned int source_variance) { MACROBLOCKD *const xd = &x->e_mbd; unsigned int recon_variance; - unsigned int var_diff; + unsigned int absvar_diff = 0; + int64_t var_error = 0; + int64_t var_factor = 0; if (*this_rd == INT64_MAX) return; @@ -2857,22 +2857,31 @@ static void rd_variance_adjustment(VP9_COMP *cpi, vp9_get_sby_perpixel_variance(cpi, &xd->plane[0].dst, bsize); #endif // CONFIG_VP9_HIGHBITDEPTH - var_diff = (source_variance > recon_variance) - ? (source_variance - recon_variance) : (recon_variance - source_variance); + if ((source_variance + recon_variance) > LOW_VAR_THRESH) { + absvar_diff = (source_variance > recon_variance) + ? (source_variance - recon_variance) + : (recon_variance - source_variance); - if ((source_variance > LOW_VAR_THRESH) && (var_diff > LOW_VAR_DIFF_THRESH)) { - unsigned int var_factor; - if (source_variance > recon_variance) { - var_factor = - MIN(VLOW_ADJ_MAX, (var_diff * VLOW_ADJ_MAX) / source_variance); - } else { - var_factor = - MIN(VHIGH_ADJ_MAX, (var_diff * VHIGH_ADJ_MAX) / source_variance); - } - *this_rd += (*this_rd * var_factor) / 100; + var_error = (200 * source_variance * recon_variance) / + ((source_variance * source_variance) + + (recon_variance * recon_variance)); + var_error = 100 - var_error; } + + // Source variance above a threshold and ref frame is intra. + // This case is targeted mainly at discouraging intra modes that give rise + // to a predictor with a low spatial complexity compared to the source. + if ((source_variance > LOW_VAR_THRESH) && (ref_frame == INTRA_FRAME) && + (source_variance > recon_variance)) { + var_factor = MIN(absvar_diff, MIN(VLOW_ADJ_MAX, var_error)); + // A second possible case of interest is where the source variance + // is very low and we wish to discourage false texture or motion trails. + } else if ((source_variance < (LOW_VAR_THRESH >> 1)) && + (recon_variance > source_variance)) { + var_factor = MIN(absvar_diff, MIN(VHIGH_ADJ_MAX, var_error)); + } + *this_rd += (*this_rd * var_factor) / 100; } -#endif void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, TileDataEnc *tile_data, @@ -3330,11 +3339,10 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2); } -#if SOURCE_VARIANCE_RD_ADJUSTMENT // Apply an adjustment to the rd value based on the similarity of the // source variance and reconstructed variance. - rd_variance_adjustment(cpi, x, bsize, &this_rd, x->source_variance); -#endif + rd_variance_adjustment(cpi, x, bsize, &this_rd, + ref_frame, x->source_variance); if (ref_frame == INTRA_FRAME) { // Keep record of best intra rd