From 18805eee6c2a0c01b045a59a6ea95a1e02ab718a Mon Sep 17 00:00:00 2001 From: Marco Date: Thu, 22 Jun 2017 14:59:27 -0700 Subject: [PATCH] vp9: Use scene detection for CBR mode. Use the scene detection for CBR mode, and use it to reset the rate control if large source sad is detected and rate correctioni fact/QP is at minimum state. Avoids large frame sizes after big content change following low content period. Only affects CBR mode for 1 pass at speeds 5, 6, 7. Change-Id: I56dd853478cd5849b32db776e9221e258998d874 --- vp9/encoder/vp9_encoder.c | 9 +++++---- vp9/encoder/vp9_ratectrl.c | 24 ++++++++++++++++++++++-- vp9/encoder/vp9_ratectrl.h | 1 + 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index bf33168e7..79d7d7a31 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -3524,12 +3524,13 @@ static void encode_without_recode_loop(VP9_COMP *cpi, size_t *size, vp9_update_noise_estimate(cpi); - // Scene detection is used for VBR mode or screen-content case. - // Make sure compute_source_sad_onepass is set (which handles SVC case - // and dynamic resize). + // Scene detection is always used for VBR mode or screen-content case. + // For other cases (e.g., CBR mode) use it for 5 <= speed < 8 for now + // (need to check encoding time cost for doing this for speed 8). if (cpi->compute_source_sad_onepass && (cpi->oxcf.rc_mode == VPX_VBR || - cpi->oxcf.content == VP9E_CONTENT_SCREEN)) + cpi->oxcf.content == VP9E_CONTENT_SCREEN || + (cpi->oxcf.speed >= 5 && cpi->oxcf.speed < 8))) vp9_scene_detection_onepass(cpi); // For 1 pass CBR SVC, only ZEROMV is allowed for spatial reference frame diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index 1b5279412..942d7ede3 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -353,6 +353,7 @@ void vp9_rc_init(const VP9EncoderConfig *oxcf, int pass, RATE_CONTROL *rc) { rc->af_ratio_onepass_vbr = 10; rc->prev_avg_source_sad_lag = 0; rc->high_source_sad = 0; + rc->reset_high_source_sad = 0; rc->high_source_sad_lagindex = -1; rc->alt_ref_gf_group = 0; rc->fac_active_worst_inter = 150; @@ -585,7 +586,7 @@ int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame, // In CBR mode, this makes sure q is between oscillating Qs to prevent // resonance. - if (cpi->oxcf.rc_mode == VPX_CBR && + if (cpi->oxcf.rc_mode == VPX_CBR && !cpi->rc.reset_high_source_sad && (!cpi->oxcf.gf_cbr_boost_pct || !(cpi->refresh_alt_ref_frame || cpi->refresh_golden_frame)) && (cpi->rc.rc_1_frame * cpi->rc.rc_2_frame == -1) && @@ -679,7 +680,8 @@ static int calc_active_worst_quality_one_pass_cbr(const VP9_COMP *cpi) { int active_worst_quality; int ambient_qp; unsigned int num_frames_weight_key = 5 * cpi->svc.number_temporal_layers; - if (cm->frame_type == KEY_FRAME) return rc->worst_quality; + if (cm->frame_type == KEY_FRAME || rc->reset_high_source_sad) + return rc->worst_quality; // For ambient_qp we use minimum of avg_frame_qindex[KEY_FRAME/INTER_FRAME] // for the first few frames following key frame. These are both initialized // to worst_quality and updated with (3/4, 1/4) average in postencode_update. @@ -1464,6 +1466,7 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) { if (oxcf->pass == 0) { if (cm->frame_type != KEY_FRAME) compute_frame_low_motion(cpi); } + if (cm->frame_type != KEY_FRAME) rc->reset_high_source_sad = 0; } void vp9_rc_postencode_update_drop_frame(VP9_COMP *cpi) { @@ -2331,6 +2334,23 @@ void vp9_scene_detection_onepass(VP9_COMP *cpi) { } } } + // For CBR non-screen content mode, check if we should reset the rate + // control. Reset is done if high_source_sad is detected and the rate + // control is at very low QP with rate correction factor at min level. + if (cpi->oxcf.rc_mode == VPX_CBR && + cpi->oxcf.content != VP9E_CONTENT_SCREEN && !cpi->use_svc) { + if (rc->high_source_sad && rc->last_q[INTER_FRAME] == rc->best_quality && + rc->avg_frame_qindex[INTER_FRAME] < (rc->best_quality << 1) && + rc->rate_correction_factors[INTER_NORMAL] == MIN_BPB_FACTOR) { + rc->rate_correction_factors[INTER_NORMAL] = 0.5; + rc->avg_frame_qindex[INTER_FRAME] = rc->worst_quality; + rc->buffer_level = rc->optimal_buffer_level; + rc->bits_off_target = rc->optimal_buffer_level; + rc->reset_high_source_sad = 1; + } + if (cm->frame_type != KEY_FRAME && rc->reset_high_source_sad) + rc->this_frame_target = rc->avg_frame_bandwidth; + } // For VBR, under scene change/high content change, force golden refresh. if (cpi->oxcf.rc_mode == VPX_VBR && cm->frame_type != KEY_FRAME && rc->high_source_sad && rc->frames_to_key > 3 && diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h index 9e4623195..c5bc173e2 100644 --- a/vp9/encoder/vp9_ratectrl.h +++ b/vp9/encoder/vp9_ratectrl.h @@ -169,6 +169,7 @@ typedef struct { int avg_frame_low_motion; int af_ratio_onepass_vbr; int force_qpmin; + int reset_high_source_sad; } RATE_CONTROL; struct VP9_COMP; -- 2.40.0