diff options
-rw-r--r-- | vp9/encoder/vp9_encodeframe.c | 16 | ||||
-rw-r--r-- | vp9/encoder/vp9_firstpass.c | 15 | ||||
-rw-r--r-- | vp9/encoder/vp9_rdopt.c | 64 | ||||
-rw-r--r-- | vp9/encoder/vp9_rdopt.h | 9 |
4 files changed, 84 insertions, 20 deletions
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 45918ecc9..10a62ef69 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -99,9 +99,9 @@ static const uint16_t VP9_HIGH_VAR_OFFS_12[64] = { }; #endif // CONFIG_VP9_HIGHBITDEPTH -static unsigned int get_sby_perpixel_variance(VP9_COMP *cpi, - const struct buf_2d *ref, - BLOCK_SIZE bs) { +unsigned int vp9_get_sby_perpixel_variance(VP9_COMP *cpi, + const struct buf_2d *ref, + BLOCK_SIZE bs) { unsigned int sse; const unsigned int var = cpi->fn_ptr[bs].vf(ref->buf, ref->stride, VP9_VAR_OFFS, 0, &sse); @@ -109,7 +109,7 @@ static unsigned int get_sby_perpixel_variance(VP9_COMP *cpi, } #if CONFIG_VP9_HIGHBITDEPTH -static unsigned int high_get_sby_perpixel_variance( +unsigned int vp9_high_get_sby_perpixel_variance( VP9_COMP *cpi, const struct buf_2d *ref, BLOCK_SIZE bs, int bd) { unsigned int var, sse; switch (bd) { @@ -1073,13 +1073,15 @@ static void rd_pick_sb_modes(VP9_COMP *cpi, #if CONFIG_VP9_HIGHBITDEPTH if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) { x->source_variance = - high_get_sby_perpixel_variance(cpi, &x->plane[0].src, bsize, xd->bd); + vp9_high_get_sby_perpixel_variance(cpi, &x->plane[0].src, + bsize, xd->bd); } else { x->source_variance = - get_sby_perpixel_variance(cpi, &x->plane[0].src, bsize); + vp9_get_sby_perpixel_variance(cpi, &x->plane[0].src, bsize); } #else - x->source_variance = get_sby_perpixel_variance(cpi, &x->plane[0].src, bsize); + x->source_variance = + vp9_get_sby_perpixel_variance(cpi, &x->plane[0].src, bsize); #endif // CONFIG_VP9_HIGHBITDEPTH // Save rdmult before it might be changed, so it can be restored later. 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 09512df18..5efa40bfc 100644 --- a/vp9/encoder/vp9_rdopt.c +++ b/vp9/encoder/vp9_rdopt.c @@ -2821,6 +2821,65 @@ 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); } +// 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 VLOW_ADJ_MAX 25 +#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 absvar_diff = 0; + int64_t var_error = 0; + int64_t var_factor = 0; + + if (*this_rd == INT64_MAX) + return; + +#if CONFIG_VP9_HIGHBITDEPTH + if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) { + recon_variance = + vp9_high_get_sby_perpixel_variance(cpi, &xd->plane[0].dst, bsize, xd->bd); + } else { + recon_variance = + vp9_get_sby_perpixel_variance(cpi, &xd->plane[0].dst, bsize); + } +#else + recon_variance = + vp9_get_sby_perpixel_variance(cpi, &xd->plane[0].dst, bsize); +#endif // CONFIG_VP9_HIGHBITDEPTH + + if ((source_variance + recon_variance) > LOW_VAR_THRESH) { + absvar_diff = (source_variance > recon_variance) + ? (source_variance - recon_variance) + : (recon_variance - source_variance); + + 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; +} + void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, TileDataEnc *tile_data, MACROBLOCK *x, @@ -3277,6 +3336,11 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2); } + // 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, + ref_frame, x->source_variance); + if (ref_frame == INTRA_FRAME) { // Keep record of best intra rd if (this_rd < best_intra_rd) { diff --git a/vp9/encoder/vp9_rdopt.h b/vp9/encoder/vp9_rdopt.h index 7bbc3c89a..459b0324b 100644 --- a/vp9/encoder/vp9_rdopt.h +++ b/vp9/encoder/vp9_rdopt.h @@ -29,6 +29,15 @@ void vp9_rd_pick_intra_mode_sb(struct VP9_COMP *cpi, struct macroblock *x, struct RD_COST *rd_cost, BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx, int64_t best_rd); +unsigned int vp9_get_sby_perpixel_variance(VP9_COMP *cpi, + const struct buf_2d *ref, + BLOCK_SIZE bs); +#if CONFIG_VP9_HIGHBITDEPTH +unsigned int vp9_high_get_sby_perpixel_variance(VP9_COMP *cpi, + const struct buf_2d *ref, + BLOCK_SIZE bs, int bd); +#endif + void vp9_rd_pick_inter_mode_sb(struct VP9_COMP *cpi, struct TileDataEnc *tile_data, struct macroblock *x, |