diff options
Diffstat (limited to 'vp8')
-rw-r--r-- | vp8/encoder/onyx_if.c | 15 | ||||
-rw-r--r-- | vp8/encoder/onyx_int.h | 2 | ||||
-rw-r--r-- | vp8/encoder/ratectrl.c | 46 | ||||
-rw-r--r-- | vp8/encoder/ratectrl.h | 2 | ||||
-rw-r--r-- | vp8/vp8_cx_iface.c | 2 |
5 files changed, 64 insertions, 3 deletions
diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index 5b452312e..c2bb23295 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -587,7 +587,8 @@ static void cyclic_background_refresh(VP8_COMP *cpi, int Q, int lf_adjustment) // Turn-off under certain conditions (i.e., away from key frame, and if // we are at good quality (low Q) and most of the blocks were skipped-encoded // in previous frame. - if (Q >= 100) { + int qp_thresh = (cpi->oxcf.screen_content_mode == 2) ? 80 : 100; + if (Q >= qp_thresh) { cpi->cyclic_refresh_mode_max_mbs_perframe = (cpi->common.mb_rows * cpi->common.mb_cols) / 10; } else if (cpi->frames_since_key > 250 && @@ -2011,6 +2012,8 @@ struct VP8_COMP* vp8_create_compressor(VP8_CONFIG *oxcf) cpi->source_alt_ref_active = 0; cpi->common.refresh_alt_ref_frame = 0; + cpi->force_maxqp = 0; + cpi->b_calculate_psnr = CONFIG_INTERNAL_STATS; #if CONFIG_INTERNAL_STATS cpi->b_calculate_ssimg = 0; @@ -4184,7 +4187,10 @@ static void encode_frame_to_data_rate */ if (cpi->cyclic_refresh_mode_enabled) { - if (cpi->current_layer==0) + // Special case for screen_content_mode with golden frame updates. + int disable_cr_gf = (cpi->oxcf.screen_content_mode == 2 && + cm->refresh_golden_frame); + if (cpi->current_layer == 0 && cpi->force_maxqp == 0 && !disable_cr_gf) cyclic_background_refresh(cpi, Q, 0); else disable_segmentation(cpi); @@ -4406,6 +4412,11 @@ static void encode_frame_to_data_rate /* transform / motion compensation build reconstruction frame */ vp8_encode_frame(cpi); + if (cpi->oxcf.screen_content_mode == 2) { + if (vp8_drop_encodedframe_overshoot(cpi, Q)) + return; + } + cpi->projected_frame_size -= vp8_estimate_entropy_savings(cpi); cpi->projected_frame_size = (cpi->projected_frame_size > 0) ? cpi->projected_frame_size : 0; #endif diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h index 846c15b46..c48e2f447 100644 --- a/vp8/encoder/onyx_int.h +++ b/vp8/encoder/onyx_int.h @@ -526,6 +526,8 @@ typedef struct VP8_COMP // Measure of average squared difference between source and denoised signal. int mse_source_denoised; + int force_maxqp; + #if CONFIG_MULTITHREAD /* multithread data */ int * mt_current_mb_col; diff --git a/vp8/encoder/ratectrl.c b/vp8/encoder/ratectrl.c index 25d7a4998..10d340880 100644 --- a/vp8/encoder/ratectrl.c +++ b/vp8/encoder/ratectrl.c @@ -1215,6 +1215,11 @@ int vp8_regulate_q(VP8_COMP *cpi, int target_bits_per_frame) { int Q = cpi->active_worst_quality; + if (cpi->force_maxqp == 1) { + cpi->active_worst_quality = cpi->worst_quality; + return cpi->worst_quality; + } + /* Reset Zbin OQ value */ cpi->mb.zbin_over_quant = 0; @@ -1559,3 +1564,44 @@ int vp8_pick_frame_size(VP8_COMP *cpi) } return 1; } +// If this just encoded frame (mcomp/transform/quant, but before loopfilter and +// pack_bitstream) has large overshoot, and was not being encoded close to the +// max QP, then drop this frame and force next frame to be encoded at max QP. +// Condition this on 1 pass CBR with screen content mode and frame dropper off. +// TODO(marpan): Should do this exit condition during the encode_frame +// (i.e., halfway during the encoding of the frame) to save cycles. +int vp8_drop_encodedframe_overshoot(VP8_COMP *cpi, int Q) { + if (cpi->pass == 0 && + cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER && + cpi->drop_frames_allowed == 0 && + cpi->common.frame_type != KEY_FRAME) { + // Note: the "projected_frame_size" from encode_frame() only gives estimate + // of mode/motion vector rate (in non-rd mode): so below we only require + // that projected_frame_size is somewhat greater than per-frame-bandwidth, + // but add additional condition with high threshold on prediction residual. + + // QP threshold: only allow dropping if we are not close to qp_max. + int thresh_qp = 3 * cpi->worst_quality >> 2; + // Rate threshold, in bytes. + int thresh_rate = 2 * (cpi->av_per_frame_bandwidth >> 3); + // Threshold for the average (over all macroblocks) of the pixel-sum + // residual error over 16x16 block. Should add QP dependence on threshold? + int thresh_pred_err_mb = (256 << 4); + int pred_err_mb = cpi->mb.prediction_error / cpi->common.MBs; + if (Q < thresh_qp && + cpi->projected_frame_size > thresh_rate && + pred_err_mb > thresh_pred_err_mb) { + // Drop this frame: advance frame counters, and set force_maxqp flag. + cpi->common.current_video_frame++; + cpi->frames_since_key++; + // Flag to indicate we will force next frame to be encoded at max QP. + cpi->force_maxqp = 1; + return 1; + } else { + cpi->force_maxqp = 0; + return 0; + } + return 0; + } + return 0; +} diff --git a/vp8/encoder/ratectrl.h b/vp8/encoder/ratectrl.h index 829697f39..703de9ff5 100644 --- a/vp8/encoder/ratectrl.h +++ b/vp8/encoder/ratectrl.h @@ -30,6 +30,8 @@ extern void vp8_compute_frame_size_bounds(VP8_COMP *cpi, int *frame_under_shoot_ /* return of 0 means drop frame */ extern int vp8_pick_frame_size(VP8_COMP *cpi); +extern int vp8_drop_encodedframe_overshoot(VP8_COMP *cpi, int Q); + #ifdef __cplusplus } // extern "C" #endif diff --git a/vp8/vp8_cx_iface.c b/vp8/vp8_cx_iface.c index db4c52887..3e3dbb036 100644 --- a/vp8/vp8_cx_iface.c +++ b/vp8/vp8_cx_iface.c @@ -199,7 +199,7 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx, RANGE_CHECK_HI(vp8_cfg, arnr_strength, 6); RANGE_CHECK(vp8_cfg, arnr_type, 1, 3); RANGE_CHECK(vp8_cfg, cq_level, 0, 63); - RANGE_CHECK_BOOL(vp8_cfg, screen_content_mode); + RANGE_CHECK_HI(vp8_cfg, screen_content_mode, 2); if (finalize && (cfg->rc_end_usage == VPX_CQ || cfg->rc_end_usage == VPX_Q)) RANGE_CHECK(vp8_cfg, cq_level, cfg->rc_min_quantizer, cfg->rc_max_quantizer); |