diff options
Diffstat (limited to 'vp9')
-rw-r--r-- | vp9/encoder/vp9_encodeframe.c | 32 | ||||
-rw-r--r-- | vp9/encoder/vp9_firstpass.c | 23 | ||||
-rw-r--r-- | vp9/encoder/vp9_rd.h | 5 | ||||
-rw-r--r-- | vp9/encoder/vp9_rdopt.c | 87 | ||||
-rw-r--r-- | vp9/encoder/vp9_temporal_filter.c | 21 |
5 files changed, 113 insertions, 55 deletions
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 9574c097a..f92705a81 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -125,19 +125,17 @@ static const uint16_t VP9_HIGH_VAR_OFFS_12[64] = { }; #endif // CONFIG_VP9_HIGHBITDEPTH -unsigned int vp9_get_sby_perpixel_variance(VP9_COMP *cpi, - const struct buf_2d *ref, - BLOCK_SIZE bs) { +unsigned int vp9_get_sby_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); - return ROUND_POWER_OF_TWO(var, num_pels_log2_lookup[bs]); + return var; } #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) { +unsigned int vp9_high_get_sby_variance(VP9_COMP *cpi, const struct buf_2d *ref, + BLOCK_SIZE bs, int bd) { unsigned int var, sse; switch (bd) { case 10: @@ -157,8 +155,24 @@ unsigned int vp9_high_get_sby_perpixel_variance(VP9_COMP *cpi, CONVERT_TO_BYTEPTR(VP9_HIGH_VAR_OFFS_8), 0, &sse); break; } - return (unsigned int)ROUND64_POWER_OF_TWO((int64_t)var, - num_pels_log2_lookup[bs]); + return var; +} +#endif // CONFIG_VP9_HIGHBITDEPTH + +unsigned int vp9_get_sby_perpixel_variance(VP9_COMP *cpi, + const struct buf_2d *ref, + BLOCK_SIZE bs) { + return ROUND_POWER_OF_TWO(vp9_get_sby_variance(cpi, ref, bs), + num_pels_log2_lookup[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) { + return (unsigned int)ROUND64_POWER_OF_TWO( + (int64_t)vp9_high_get_sby_variance(cpi, ref, bs, bd), + num_pels_log2_lookup[bs]); } #endif // CONFIG_VP9_HIGHBITDEPTH diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index d09acf78b..caa58e7a8 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -2010,8 +2010,7 @@ static double calc_kf_frame_boost(VP9_COMP *cpi, return VPXMIN(frame_boost, max_boost * boost_q_correction); } -static int calc_arf_boost(VP9_COMP *cpi, int offset, int f_frames, int b_frames, - int *f_boost, int *b_boost) { +static int calc_arf_boost(VP9_COMP *cpi, int f_frames, int b_frames) { TWO_PASS *const twopass = &cpi->twopass; int i; double boost_score = 0.0; @@ -2026,7 +2025,7 @@ static int calc_arf_boost(VP9_COMP *cpi, int offset, int f_frames, int b_frames, // Search forward from the proposed arf/next gf position. for (i = 0; i < f_frames; ++i) { - const FIRSTPASS_STATS *this_frame = read_frame_stats(twopass, i + offset); + const FIRSTPASS_STATS *this_frame = read_frame_stats(twopass, i); if (this_frame == NULL) break; // Update the motion related elements to the boost calculation. @@ -2036,8 +2035,7 @@ static int calc_arf_boost(VP9_COMP *cpi, int offset, int f_frames, int b_frames, // We want to discount the flash frame itself and the recovery // frame that follows as both will have poor scores. - flash_detected = detect_flash(twopass, i + offset) || - detect_flash(twopass, i + offset + 1); + flash_detected = detect_flash(twopass, i) || detect_flash(twopass, i + 1); // Accumulate the effect of prediction quality decay. if (!flash_detected) { @@ -2053,7 +2051,7 @@ static int calc_arf_boost(VP9_COMP *cpi, int offset, int f_frames, int b_frames, this_frame_mv_in_out, GF_MAX_BOOST); } - *f_boost = (int)boost_score; + arf_boost = (int)boost_score; // Reset for backward looking loop. boost_score = 0.0; @@ -2066,7 +2064,7 @@ static int calc_arf_boost(VP9_COMP *cpi, int offset, int f_frames, int b_frames, // Search backward towards last gf position. for (i = -1; i >= -b_frames; --i) { - const FIRSTPASS_STATS *this_frame = read_frame_stats(twopass, i + offset); + const FIRSTPASS_STATS *this_frame = read_frame_stats(twopass, i); if (this_frame == NULL) break; // Update the motion related elements to the boost calculation. @@ -2076,8 +2074,7 @@ static int calc_arf_boost(VP9_COMP *cpi, int offset, int f_frames, int b_frames, // We want to discount the the flash frame itself and the recovery // frame that follows as both will have poor scores. - flash_detected = detect_flash(twopass, i + offset) || - detect_flash(twopass, i + offset + 1); + flash_detected = detect_flash(twopass, i) || detect_flash(twopass, i + 1); // Cumulative effect of prediction quality decay. if (!flash_detected) { @@ -2092,9 +2089,8 @@ static int calc_arf_boost(VP9_COMP *cpi, int offset, int f_frames, int b_frames, calc_frame_boost(cpi, this_frame, &sr_accumulator, this_frame_mv_in_out, GF_MAX_BOOST); } - *b_boost = (int)boost_score; + arf_boost += (int)boost_score; - arf_boost = (*f_boost + *b_boost); if (arf_boost < ((b_frames + f_frames) * 20)) arf_boost = ((b_frames + f_frames) * 20); arf_boost = VPXMAX(arf_boost, MIN_ARF_GF_BOOST); @@ -2439,8 +2435,6 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { const double av_err = get_distribution_av_err(cpi, twopass); unsigned int allow_alt_ref = is_altref_enabled(cpi); - int f_boost = 0; - int b_boost = 0; int flash_detected; int active_max_gf_interval; int active_min_gf_interval; @@ -2606,8 +2600,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) { : VPXMAX(0, rc->frames_to_key - i); // Calculate the boost for alt ref. - rc->gfu_boost = - calc_arf_boost(cpi, 0, forward_frames, i - 1, &f_boost, &b_boost); + rc->gfu_boost = calc_arf_boost(cpi, forward_frames, (i - 1)); rc->source_alt_ref_pending = 1; // Test to see if multi arf is appropriate. diff --git a/vp9/encoder/vp9_rd.h b/vp9/encoder/vp9_rd.h index 230508718..59022c106 100644 --- a/vp9/encoder/vp9_rd.h +++ b/vp9/encoder/vp9_rd.h @@ -194,10 +194,15 @@ void vp9_setup_pred_block(const MACROBLOCKD *xd, int vp9_get_intra_cost_penalty(const struct VP9_COMP *const cpi, BLOCK_SIZE bsize, int qindex, int qdelta); +unsigned int vp9_get_sby_variance(struct VP9_COMP *cpi, + const struct buf_2d *ref, BLOCK_SIZE bs); unsigned int vp9_get_sby_perpixel_variance(struct VP9_COMP *cpi, const struct buf_2d *ref, BLOCK_SIZE bs); #if CONFIG_VP9_HIGHBITDEPTH +unsigned int vp9_high_get_sby_variance(struct VP9_COMP *cpi, + const struct buf_2d *ref, BLOCK_SIZE bs, + int bd); unsigned int vp9_high_get_sby_perpixel_variance(struct VP9_COMP *cpi, const struct buf_2d *ref, BLOCK_SIZE bs, int bd); diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c index afdb60f18..2ba6378c5 100644 --- a/vp9/encoder/vp9_rdopt.c +++ b/vp9/encoder/vp9_rdopt.c @@ -2876,57 +2876,82 @@ void vp9_rd_pick_intra_mode_sb(VP9_COMP *cpi, MACROBLOCK *x, RD_COST *rd_cost, // 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 +#define VERY_LOW_VAR_THRESH 2 +#define LOW_VAR_THRESH 5 +#define VAR_MULT 100 +static unsigned int max_var_adjust[VP9E_CONTENT_INVALID] = { 16, 16, 100 }; + 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 rec_variance; + unsigned int src_variance; + unsigned int src_rec_min; unsigned int absvar_diff = 0; - int64_t var_error = 0; - int64_t var_factor = 0; + unsigned int var_factor = 0; + unsigned int adj_max; + vp9e_tune_content content_type = cpi->oxcf.content; 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, + if (source_variance > 0) { + rec_variance = vp9_high_get_sby_perpixel_variance(cpi, &xd->plane[0].dst, bsize, xd->bd); + src_variance = source_variance; + } else { + rec_variance = + vp9_high_get_sby_variance(cpi, &xd->plane[0].dst, bsize, xd->bd); + src_variance = + vp9_high_get_sby_variance(cpi, &x->plane[0].src, bsize, xd->bd); + } } else { - recon_variance = - vp9_get_sby_perpixel_variance(cpi, &xd->plane[0].dst, bsize); + if (source_variance > 0) { + rec_variance = + vp9_get_sby_perpixel_variance(cpi, &xd->plane[0].dst, bsize); + src_variance = source_variance; + } else { + rec_variance = vp9_get_sby_variance(cpi, &xd->plane[0].dst, bsize); + src_variance = vp9_get_sby_variance(cpi, &x->plane[0].src, bsize); + } } #else - recon_variance = vp9_get_sby_perpixel_variance(cpi, &xd->plane[0].dst, bsize); + if (source_variance > 0) { + rec_variance = vp9_get_sby_perpixel_variance(cpi, &xd->plane[0].dst, bsize); + src_variance = source_variance; + } else { + rec_variance = vp9_get_sby_variance(cpi, &xd->plane[0].dst, bsize); + src_variance = vp9_get_sby_variance(cpi, &x->plane[0].src, 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); + // Lower of source (raw per pixel value) and recon variance. Note that + // if the source per pixel is 0 then the recon value here will not be per + // pixel (see above) so will likely be much larger. + src_rec_min = VPXMIN(source_variance, rec_variance); - var_error = ((int64_t)200 * source_variance * recon_variance) / - (((int64_t)source_variance * source_variance) + - ((int64_t)recon_variance * recon_variance)); - var_error = 100 - var_error; - } + if (src_rec_min > LOW_VAR_THRESH) return; + + absvar_diff = (src_variance > rec_variance) ? (src_variance - rec_variance) + : (rec_variance - src_variance); + + adj_max = max_var_adjust[content_type]; + + var_factor = + (unsigned int)((int64_t)VAR_MULT * absvar_diff) / VPXMAX(1, src_variance); + var_factor = VPXMIN(adj_max, var_factor); - // 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 = VPXMIN(absvar_diff, VPXMIN(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 = VPXMIN(absvar_diff, VPXMIN(VHIGH_ADJ_MAX, var_error)); - } *this_rd += (*this_rd * var_factor) / 100; + + if (content_type == VP9E_CONTENT_FILM) { + if (src_rec_min <= VERY_LOW_VAR_THRESH) { + if (ref_frame == INTRA_FRAME) *this_rd *= 2; + if (bsize > 6) *this_rd *= 2; + } + } } // Do we have an internal image edge (e.g. formatting bars). diff --git a/vp9/encoder/vp9_temporal_filter.c b/vp9/encoder/vp9_temporal_filter.c index 630794156..2758c42ae 100644 --- a/vp9/encoder/vp9_temporal_filter.c +++ b/vp9/encoder/vp9_temporal_filter.c @@ -350,6 +350,27 @@ void vp9_temporal_filter_iterate_row_c(VP9_COMP *cpi, ThreadData *td, td->mb.mv_limits.col_max = ((mb_cols - 1 - mb_col) * 16) + (17 - 2 * VP9_INTERP_EXTEND); + if (cpi->oxcf.content == VP9E_CONTENT_FILM) { + unsigned int src_variance; + struct buf_2d src; + + src.buf = f->y_buffer + mb_y_offset; + src.stride = f->y_stride; + +#if CONFIG_VP9_HIGHBITDEPTH + if (mbd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) { + src_variance = + vp9_high_get_sby_perpixel_variance(cpi, &src, BLOCK_16X16, mbd->bd); + } else { + src_variance = vp9_get_sby_perpixel_variance(cpi, &src, BLOCK_16X16); + } +#else + src_variance = vp9_get_sby_perpixel_variance(cpi, &src, BLOCK_16X16); +#endif // CONFIG_VP9_HIGHBITDEPTH + + if (src_variance <= 2) strength = VPXMAX(0, (int)strength - 2); + } + for (frame = 0; frame < frame_count; frame++) { const uint32_t thresh_low = 10000; const uint32_t thresh_high = 20000; |