VP8: For high overshoot, force drop frame and max-out QP.
This allows rate control to react to content of current frame being encoded. Enabling this feature via the setting: screen_content_mode = 2. Change-Id: Ib2c6670551d96f4907495d5b7b76bb8c49e673db
This commit is contained in:
@@ -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
|
// 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
|
// we are at good quality (low Q) and most of the blocks were skipped-encoded
|
||||||
// in previous frame.
|
// 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->cyclic_refresh_mode_max_mbs_perframe =
|
||||||
(cpi->common.mb_rows * cpi->common.mb_cols) / 10;
|
(cpi->common.mb_rows * cpi->common.mb_cols) / 10;
|
||||||
} else if (cpi->frames_since_key > 250 &&
|
} 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->source_alt_ref_active = 0;
|
||||||
cpi->common.refresh_alt_ref_frame = 0;
|
cpi->common.refresh_alt_ref_frame = 0;
|
||||||
|
|
||||||
|
cpi->force_maxqp = 0;
|
||||||
|
|
||||||
cpi->b_calculate_psnr = CONFIG_INTERNAL_STATS;
|
cpi->b_calculate_psnr = CONFIG_INTERNAL_STATS;
|
||||||
#if CONFIG_INTERNAL_STATS
|
#if CONFIG_INTERNAL_STATS
|
||||||
cpi->b_calculate_ssimg = 0;
|
cpi->b_calculate_ssimg = 0;
|
||||||
@@ -4184,7 +4187,10 @@ static void encode_frame_to_data_rate
|
|||||||
*/
|
*/
|
||||||
if (cpi->cyclic_refresh_mode_enabled)
|
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);
|
cyclic_background_refresh(cpi, Q, 0);
|
||||||
else
|
else
|
||||||
disable_segmentation(cpi);
|
disable_segmentation(cpi);
|
||||||
@@ -4406,6 +4412,11 @@ static void encode_frame_to_data_rate
|
|||||||
/* transform / motion compensation build reconstruction frame */
|
/* transform / motion compensation build reconstruction frame */
|
||||||
vp8_encode_frame(cpi);
|
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 -= vp8_estimate_entropy_savings(cpi);
|
||||||
cpi->projected_frame_size = (cpi->projected_frame_size > 0) ? cpi->projected_frame_size : 0;
|
cpi->projected_frame_size = (cpi->projected_frame_size > 0) ? cpi->projected_frame_size : 0;
|
||||||
#endif
|
#endif
|
||||||
|
@@ -526,6 +526,8 @@ typedef struct VP8_COMP
|
|||||||
// Measure of average squared difference between source and denoised signal.
|
// Measure of average squared difference between source and denoised signal.
|
||||||
int mse_source_denoised;
|
int mse_source_denoised;
|
||||||
|
|
||||||
|
int force_maxqp;
|
||||||
|
|
||||||
#if CONFIG_MULTITHREAD
|
#if CONFIG_MULTITHREAD
|
||||||
/* multithread data */
|
/* multithread data */
|
||||||
int * mt_current_mb_col;
|
int * mt_current_mb_col;
|
||||||
|
@@ -1215,6 +1215,11 @@ int vp8_regulate_q(VP8_COMP *cpi, int target_bits_per_frame)
|
|||||||
{
|
{
|
||||||
int Q = cpi->active_worst_quality;
|
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 */
|
/* Reset Zbin OQ value */
|
||||||
cpi->mb.zbin_over_quant = 0;
|
cpi->mb.zbin_over_quant = 0;
|
||||||
|
|
||||||
@@ -1559,3 +1564,44 @@ int vp8_pick_frame_size(VP8_COMP *cpi)
|
|||||||
}
|
}
|
||||||
return 1;
|
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;
|
||||||
|
}
|
||||||
|
@@ -30,6 +30,8 @@ extern void vp8_compute_frame_size_bounds(VP8_COMP *cpi, int *frame_under_shoot_
|
|||||||
/* return of 0 means drop frame */
|
/* return of 0 means drop frame */
|
||||||
extern int vp8_pick_frame_size(VP8_COMP *cpi);
|
extern int vp8_pick_frame_size(VP8_COMP *cpi);
|
||||||
|
|
||||||
|
extern int vp8_drop_encodedframe_overshoot(VP8_COMP *cpi, int Q);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
@@ -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_HI(vp8_cfg, arnr_strength, 6);
|
||||||
RANGE_CHECK(vp8_cfg, arnr_type, 1, 3);
|
RANGE_CHECK(vp8_cfg, arnr_type, 1, 3);
|
||||||
RANGE_CHECK(vp8_cfg, cq_level, 0, 63);
|
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))
|
if (finalize && (cfg->rc_end_usage == VPX_CQ || cfg->rc_end_usage == VPX_Q))
|
||||||
RANGE_CHECK(vp8_cfg, cq_level,
|
RANGE_CHECK(vp8_cfg, cq_level,
|
||||||
cfg->rc_min_quantizer, cfg->rc_max_quantizer);
|
cfg->rc_min_quantizer, cfg->rc_max_quantizer);
|
||||||
|
@@ -326,6 +326,8 @@ enum vp8e_enc_control_id {
|
|||||||
VP8E_SET_TEMPORAL_LAYER_ID,
|
VP8E_SET_TEMPORAL_LAYER_ID,
|
||||||
|
|
||||||
/*!\brief Codec control function to set encoder screen content mode.
|
/*!\brief Codec control function to set encoder screen content mode.
|
||||||
|
*
|
||||||
|
* 0: off, 1: On, 2: On with more aggressive rate control.
|
||||||
*
|
*
|
||||||
* Supported in codecs: VP8
|
* Supported in codecs: VP8
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user