diff options
author | Paul Wilkins <paulwilkins@google.com> | 2021-03-04 21:17:28 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2021-03-04 21:17:28 +0000 |
commit | 3cc45a052212616ae00fad2c8135a60b32effc26 (patch) | |
tree | d3df759e963f4ee4475e9fb18355a70142f3e464 | |
parent | a58265f7953ed7ce4c740761d56f320927436403 (diff) | |
parent | d0567bd779febe995020668cc7f6c1193e3e41d6 (diff) | |
download | libvpx-3cc45a052212616ae00fad2c8135a60b32effc26.tar.gz libvpx-3cc45a052212616ae00fad2c8135a60b32effc26.tar.bz2 libvpx-3cc45a052212616ae00fad2c8135a60b32effc26.zip |
Merge "Add fields into RC for Vizier ML experiments."
-rw-r--r-- | vp9/encoder/vp9_encoder.c | 1 | ||||
-rw-r--r-- | vp9/encoder/vp9_encoder.h | 1 | ||||
-rw-r--r-- | vp9/encoder/vp9_ext_ratectrl.h | 2 | ||||
-rw-r--r-- | vp9/encoder/vp9_firstpass.c | 164 | ||||
-rw-r--r-- | vp9/encoder/vp9_ratectrl.h | 13 | ||||
-rw-r--r-- | vp9/encoder/vp9_rd.c | 103 | ||||
-rw-r--r-- | vp9/encoder/vp9_rd.h | 14 |
7 files changed, 257 insertions, 41 deletions
diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 2757bc428..ecd15cb01 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -2317,6 +2317,7 @@ VP9_COMP *vp9_create_compressor(const VP9EncoderConfig *oxcf, cpi->frame_info = vp9_get_frame_info(oxcf); vp9_rc_init(&cpi->oxcf, oxcf->pass, &cpi->rc); + vp9_init_rd_parameters(cpi); init_frame_indexes(cm); cpi->partition_search_skippable_frame = 0; diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h index 8763a5e78..12520fb82 100644 --- a/vp9/encoder/vp9_encoder.h +++ b/vp9/encoder/vp9_encoder.h @@ -746,6 +746,7 @@ typedef struct VP9_COMP { // Ambient reconstruction err target for force key frames int64_t ambient_err; + RD_CONTROL rd_ctrl; RD_OPT rd; CODING_CONTEXT coding_context; diff --git a/vp9/encoder/vp9_ext_ratectrl.h b/vp9/encoder/vp9_ext_ratectrl.h index 214236308..74fd68b96 100644 --- a/vp9/encoder/vp9_ext_ratectrl.h +++ b/vp9/encoder/vp9_ext_ratectrl.h @@ -43,6 +43,6 @@ vpx_codec_err_t vp9_extrc_update_encodeframe_result( EXT_RATECTRL *ext_ratectrl, int64_t bit_count, const YV12_BUFFER_CONFIG *source_frame, const YV12_BUFFER_CONFIG *coded_frame, uint32_t bit_depth, - uint32_t input_bit_depth, int actual_encoding_qindex); + uint32_t input_bit_depth, const int actual_encoding_qindex); #endif // VPX_VP9_ENCODER_VP9_EXT_RATECTRL_H_ diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 2a9cf5289..fe7abef07 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -54,6 +54,31 @@ #define NCOUNT_INTRA_THRESH 8192 #define NCOUNT_INTRA_FACTOR 3 +#define SR_DIFF_PART 0.0015 +#define INTRA_PART 0.005 +#define DEFAULT_DECAY_LIMIT 0.75 +#define LOW_SR_DIFF_TRHESH 0.1 +#define SR_DIFF_MAX 128.0 +#define LOW_CODED_ERR_PER_MB 10.0 +#define NCOUNT_FRAME_II_THRESH 6.0 +#define BASELINE_ERR_PER_MB 12500.0 +#define GF_MAX_FRAME_BOOST 96.0 + +#ifdef AGGRESSIVE_VBR +#define KF_MAX_FRAME_BOOST 80.0 +#define MAX_KF_TOT_BOOST 4800 +#else +#define KF_MAX_FRAME_BOOST 96.0 +#define MAX_KF_TOT_BOOST 5400 +#endif + +#define ZM_POWER_FACTOR 0.75 +#define MINQ_ADJ_LIMIT 48 +#define MINQ_ADJ_LIMIT_CQ 20 +#define HIGH_UNDERSHOOT_RATIO 2 +#define AV_WQ_FACTOR 4.0 +#define DEF_EPMB_LOW 2000.0 + #define DOUBLE_DIVIDE_CHECK(x) ((x) < 0 ? (x)-0.000001 : (x) + 0.000001) #if ARF_STATS_OUTPUT @@ -1807,14 +1832,6 @@ void vp9_init_second_pass(VP9_COMP *cpi) { twopass->arnr_strength_adjustment = 0; } -#define SR_DIFF_PART 0.0015 -#define INTRA_PART 0.005 -#define DEFAULT_DECAY_LIMIT 0.75 -#define LOW_SR_DIFF_TRHESH 0.1 -#define SR_DIFF_MAX 128.0 -#define LOW_CODED_ERR_PER_MB 10.0 -#define NCOUNT_FRAME_II_THRESH 6.0 - static double get_sr_decay_rate(const FRAME_INFO *frame_info, const FIRSTPASS_STATS *frame) { double sr_diff = (frame->sr_coded_error - frame->coded_error); @@ -1853,8 +1870,6 @@ static double get_zero_motion_factor(const FRAME_INFO *frame_info, return VPXMIN(sr_decay, zero_motion_pct); } -#define ZM_POWER_FACTOR 0.75 - static double get_prediction_decay_rate(const FRAME_INFO *frame_info, const FIRSTPASS_STATS *frame_stats) { const double sr_decay_rate = get_sr_decay_rate(frame_info, frame_stats); @@ -1942,8 +1957,6 @@ static void accumulate_frame_motion_stats(const FIRSTPASS_STATS *stats, } } -#define BASELINE_ERR_PER_MB 12500.0 -#define GF_MAX_BOOST 96.0 static double calc_frame_boost(const FRAME_INFO *frame_info, const FIRSTPASS_STATS *this_frame, int avg_frame_qindex, @@ -1965,7 +1978,7 @@ static double calc_frame_boost(const FRAME_INFO *frame_info, // Q correction and scalling frame_boost = frame_boost * boost_q_correction; - return VPXMIN(frame_boost, GF_MAX_BOOST * boost_q_correction); + return VPXMIN(frame_boost, GF_MAX_FRAME_BOOST * boost_q_correction); } static double kf_err_per_mb(VP9_COMP *cpi) { @@ -3159,14 +3172,6 @@ static int test_candidate_kf(const FIRST_PASS_INFO *first_pass_info, #define MIN_SCAN_FRAMES_FOR_KF_BOOST 32 #define KF_ABS_ZOOM_THRESH 6.0 -#ifdef AGGRESSIVE_VBR -#define KF_MAX_FRAME_BOOST 80.0 -#define MAX_KF_TOT_BOOST 4800 -#else -#define KF_MAX_FRAME_BOOST 96.0 -#define MAX_KF_TOT_BOOST 5400 -#endif - int vp9_get_frames_to_next_key(const VP9EncoderConfig *oxcf, const FRAME_INFO *frame_info, const FIRST_PASS_INFO *first_pass_info, @@ -3470,6 +3475,113 @@ static int is_skippable_frame(const VP9_COMP *cpi) { twopass->stats_in->pcnt_inter - twopass->stats_in->pcnt_motion == 1); } +// Configure image size specific vizier parameters. +// Later these will be set via additional command line options +static void init_vizier_params(RATE_CONTROL *const rc, int screen_area) { + if (1) { + // Force defaults for now + rc->active_wq_factor = AV_WQ_FACTOR; + rc->base_err_per_mb = BASELINE_ERR_PER_MB; + rc->sr_default_decay_limit = DEFAULT_DECAY_LIMIT; + rc->sr_diff_part = SR_DIFF_PART; + rc->gf_frame_max_boost = GF_MAX_FRAME_BOOST; + rc->gf_max_total_boost = MAX_GF_BOOST; + rc->kf_err_per_mb = DEF_EPMB_LOW; + rc->kf_frame_max_boost_first = KF_MAX_FRAME_BOOST; // Max for first kf. + rc->kf_frame_max_boost_subs = KF_MAX_FRAME_BOOST / 2; // Max for other kfs. + rc->kf_max_total_boost = MAX_KF_TOT_BOOST; + rc->zm_power_factor = ZM_POWER_FACTOR; + } else { + // Vizer experimental parameters from training. + // Later these will be set via the command line. + if (screen_area <= 176 * 144) { + rc->active_wq_factor = 46.0; + rc->base_err_per_mb = 37597.399760969536; + rc->sr_default_decay_limit = 0.3905639800962774; + rc->sr_diff_part = 0.009599023654146284; + rc->gf_frame_max_boost = 87.27362648627846; + rc->gf_max_total_boost = MAX_GF_BOOST; + rc->kf_err_per_mb = 1854.8255436877148; + rc->kf_frame_max_boost_first = KF_MAX_FRAME_BOOST; + rc->kf_frame_max_boost_subs = rc->kf_frame_max_boost_first / 2; + rc->kf_max_total_boost = MAX_KF_TOT_BOOST; + rc->zm_power_factor = 2.93715229184991; + } else if (screen_area <= 320 * 240) { + rc->active_wq_factor = 55.0; + rc->base_err_per_mb = 34525.33177195309; + rc->sr_default_decay_limit = 0.23901360046804604; + rc->sr_diff_part = 0.008581014394766773; + rc->gf_frame_max_boost = 127.34978204980285; + rc->gf_max_total_boost = MAX_GF_BOOST; + rc->kf_err_per_mb = 723.8337508755031; + rc->kf_frame_max_boost_first = KF_MAX_FRAME_BOOST; + rc->kf_frame_max_boost_subs = rc->kf_frame_max_boost_first / 2; + rc->kf_max_total_boost = MAX_KF_TOT_BOOST; + rc->zm_power_factor = 3.5299221493593413; + } else if (screen_area <= 640 * 360) { + rc->active_wq_factor = 12.5; + rc->base_err_per_mb = 18823.978018028298; + rc->sr_default_decay_limit = 0.6043527690301296; + rc->sr_diff_part = 0.00343296783885544; + rc->gf_frame_max_boost = 75.17672317013668; + rc->gf_max_total_boost = MAX_GF_BOOST; + rc->kf_err_per_mb = 422.2871502380377; + rc->kf_frame_max_boost_first = KF_MAX_FRAME_BOOST; + rc->kf_frame_max_boost_subs = rc->kf_frame_max_boost_first / 2; + rc->kf_max_total_boost = MAX_KF_TOT_BOOST; + rc->zm_power_factor = 2.265742666649307; + } else if (screen_area <= 854 * 480) { + rc->active_wq_factor = 51.5; + rc->base_err_per_mb = 33718.98307662595; + rc->sr_default_decay_limit = 0.33633414970713393; + rc->sr_diff_part = 0.00868988716928333; + rc->gf_frame_max_boost = 85.2868528581522; + rc->gf_max_total_boost = MAX_GF_BOOST; + rc->kf_err_per_mb = 1513.4883914008383; + rc->kf_frame_max_boost_first = KF_MAX_FRAME_BOOST; + rc->kf_frame_max_boost_subs = rc->kf_frame_max_boost_first / 2; + rc->kf_max_total_boost = MAX_KF_TOT_BOOST; + rc->zm_power_factor = 3.552278528517416; + } else if (screen_area <= 1280 * 720) { + rc->active_wq_factor = 41.5; + rc->base_err_per_mb = 29527.46375825401; + rc->sr_default_decay_limit = 0.5009117586299728; + rc->sr_diff_part = 0.005007364627260114; + rc->gf_frame_max_boost = GF_MAX_FRAME_BOOST; + rc->gf_max_total_boost = MAX_GF_BOOST; + rc->kf_err_per_mb = 998.6342911785146; + rc->kf_frame_max_boost_first = KF_MAX_FRAME_BOOST; + rc->kf_frame_max_boost_subs = rc->kf_frame_max_boost_first / 2; + rc->kf_max_total_boost = MAX_KF_TOT_BOOST; + rc->zm_power_factor = 2.568627575572356; + } else if (screen_area <= 1920 * 1080) { + rc->active_wq_factor = 31.0; + rc->base_err_per_mb = 34474.723463367416; + rc->sr_default_decay_limit = 0.23346886902707745; + rc->sr_diff_part = 0.011431716637966029; + rc->gf_frame_max_boost = 81.00472969483079; + rc->gf_max_total_boost = MAX_GF_BOOST; + rc->kf_err_per_mb = 35931.25734431429; + rc->kf_frame_max_boost_first = KF_MAX_FRAME_BOOST; + rc->kf_frame_max_boost_subs = rc->kf_frame_max_boost_first / 2; + rc->kf_max_total_boost = MAX_KF_TOT_BOOST; + rc->zm_power_factor = 5.5776463538431935; + } else { + rc->active_wq_factor = AV_WQ_FACTOR; + rc->base_err_per_mb = BASELINE_ERR_PER_MB; + rc->sr_default_decay_limit = DEFAULT_DECAY_LIMIT; + rc->sr_diff_part = SR_DIFF_PART; + rc->gf_frame_max_boost = GF_MAX_FRAME_BOOST; + rc->gf_max_total_boost = MAX_GF_BOOST; + rc->kf_err_per_mb = DEF_EPMB_LOW; + rc->kf_frame_max_boost_first = KF_MAX_FRAME_BOOST; + rc->kf_frame_max_boost_subs = rc->kf_frame_max_boost_first / 2; + rc->kf_max_total_boost = MAX_KF_TOT_BOOST; + rc->zm_power_factor = ZM_POWER_FACTOR; + } + } +} + void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { VP9_COMMON *const cm = &cpi->common; RATE_CONTROL *const rc = &cpi->rc; @@ -3480,6 +3592,13 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { if (!twopass->stats_in) return; + // Configure image size specific vizier parameters + if (cm->current_video_frame == 0) { + unsigned int screen_area = (cm->width * cm->height); + + init_vizier_params(rc, screen_area); + } + // If this is an arf frame then we dont want to read the stats file or // advance the input pointer as we already have what we need. if (gf_group->update_type[gf_group->index] == ARF_UPDATE) { @@ -3605,9 +3724,6 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) { subtract_stats(&twopass->total_left_stats, &this_frame); } -#define MINQ_ADJ_LIMIT 48 -#define MINQ_ADJ_LIMIT_CQ 20 -#define HIGH_UNDERSHOOT_RATIO 2 void vp9_twopass_postencode_update(VP9_COMP *cpi) { TWO_PASS *const twopass = &cpi->twopass; RATE_CONTROL *const rc = &cpi->rc; diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h index 0120f90a0..7437d309e 100644 --- a/vp9/encoder/vp9_ratectrl.h +++ b/vp9/encoder/vp9_ratectrl.h @@ -204,6 +204,19 @@ typedef struct { int preserve_arf_as_gld; int preserve_next_arf_as_gld; int show_arf_as_gld; + + // Vizeir project experimental rate control parameters. + double active_wq_factor; + double base_err_per_mb; + double sr_default_decay_limit; + double sr_diff_part; + double kf_frame_max_boost_first; // Max for first kf in a chunk. + double kf_frame_max_boost_subs; // Max for subsequent mid chunk kfs. + double kf_max_total_boost; + double kf_err_per_mb; + double gf_frame_max_boost; + double gf_max_total_boost; + double zm_power_factor; } RATE_CONTROL; struct VP9_COMP; diff --git a/vp9/encoder/vp9_rd.c b/vp9/encoder/vp9_rd.c index 34c74424c..b126d8708 100644 --- a/vp9/encoder/vp9_rd.c +++ b/vp9/encoder/vp9_rd.c @@ -197,28 +197,99 @@ static const int rd_boost_factor[16] = { 64, 32, 32, 32, 24, 16, 12, 12, static const int rd_frame_type_factor[FRAME_UPDATE_TYPES] = { 128, 144, 128, 128, 144, 144 }; +// Configure Vizier RD parameters. +// Later this function will use passed in command line values. +void vp9_init_rd_parameters(VP9_COMP *cpi) { + RD_CONTROL *const rdc = &cpi->rd_ctrl; + unsigned int screen_area = (cpi->common.width * cpi->common.height); + + // Make sure this function is floating point safe. + vpx_clear_system_state(); + + if (1) { + // Non/pre-Vizer defaults + rdc->rd_mult_q_sq_inter_low_qp = 4.0; + rdc->rd_mult_q_sq_inter_mid_qp = 4.5; + rdc->rd_mult_q_sq_inter_high_qp = 3.0; + rdc->rd_mult_q_sq_key_ultralow_qp = 4.0; + rdc->rd_mult_q_sq_key_low_qp = 3.5; + rdc->rd_mult_q_sq_key_mid_qp = 4.5; + rdc->rd_mult_q_sq_key_high_qp = 7.5; + } else if (screen_area <= 176 * 144) { + rdc->rd_mult_q_sq_inter_high_qp = 4.295745965132044; + rdc->rd_mult_q_sq_inter_low_qp = 4.0718581295922025; + rdc->rd_mult_q_sq_inter_mid_qp = 4.031435609256739; + rdc->rd_mult_q_sq_key_low_qp = 5.7037775720838155; + rdc->rd_mult_q_sq_key_mid_qp = 4.72424015517201; + rdc->rd_mult_q_sq_key_ultralow_qp = 4.290774097327333; + } else if (screen_area <= 320 * 240) { + rdc->rd_mult_q_sq_inter_high_qp = 4.388244213131458; + rdc->rd_mult_q_sq_inter_low_qp = 4.506676356706102; + rdc->rd_mult_q_sq_inter_mid_qp = 4.489349899621181; + rdc->rd_mult_q_sq_key_low_qp = 4.497000582319771; + rdc->rd_mult_q_sq_key_mid_qp = 4.2825894884789735; + rdc->rd_mult_q_sq_key_ultralow_qp = 4.217074424696166; + } else if (screen_area <= 640 * 360) { + rdc->rd_mult_q_sq_inter_high_qp = 4.3702861603380025; + rdc->rd_mult_q_sq_inter_low_qp = 4.730644123689013; + rdc->rd_mult_q_sq_inter_mid_qp = 4.314589509578551; + rdc->rd_mult_q_sq_key_low_qp = 6.068652999601526; + rdc->rd_mult_q_sq_key_mid_qp = 4.817707474077241; + rdc->rd_mult_q_sq_key_ultralow_qp = 4.576902541873747; + } else if (screen_area <= 854 * 480) { + rdc->rd_mult_q_sq_inter_high_qp = 3.969083125219539; + rdc->rd_mult_q_sq_inter_low_qp = 4.811470143416073; + rdc->rd_mult_q_sq_inter_mid_qp = 4.621618127750201; + rdc->rd_mult_q_sq_key_low_qp = 5.073157238799473; + rdc->rd_mult_q_sq_key_mid_qp = 5.7587672849242635; + rdc->rd_mult_q_sq_key_ultralow_qp = 4.9854544277222566; + } else if (screen_area <= 1280 * 720) { + rdc->rd_mult_q_sq_inter_high_qp = 4.410712348825541; + rdc->rd_mult_q_sq_inter_low_qp = 5.119381136011107; + rdc->rd_mult_q_sq_inter_mid_qp = 4.518613675766538; + rdc->rd_mult_q_sq_key_low_qp = 5.848703119971484; + rdc->rd_mult_q_sq_key_mid_qp = 5.368947246228739; + rdc->rd_mult_q_sq_key_ultralow_qp = 3.9468491666607326; + } else if (screen_area <= 1920 * 1080) { + rdc->rd_mult_q_sq_inter_high_qp = 3.2141187537667797; + rdc->rd_mult_q_sq_inter_low_qp = 6.00569815296199; + rdc->rd_mult_q_sq_inter_mid_qp = 3.932565684947023; + rdc->rd_mult_q_sq_key_low_qp = 10.582906599488298; + rdc->rd_mult_q_sq_key_mid_qp = 6.274162346360692; + rdc->rd_mult_q_sq_key_ultralow_qp = 4.399795006320089; + } +} + int vp9_compute_rd_mult_based_on_qindex(const VP9_COMP *cpi, int qindex) { - // largest dc_quant is 21387, therefore rdmult should always fit in int32_t + const RD_CONTROL *rdc = &cpi->rd_ctrl; const int q = vp9_dc_quant(qindex, 0, cpi->common.bit_depth); - uint32_t rdmult = q * q; + // largest dc_quant is 21387, therefore rdmult should fit in int32_t + int rdmult = q * q; + + // Make sure this function is floating point safe. + vpx_clear_system_state(); if (cpi->common.frame_type != KEY_FRAME) { - if (qindex < 128) - rdmult = rdmult * 4; - else if (qindex < 190) - rdmult = rdmult * 4 + rdmult / 2; - else - rdmult = rdmult * 3; + if (qindex < 128) { + rdmult = (int)((double)rdmult * rdc->rd_mult_q_sq_inter_low_qp); + } else if (qindex < 190) { + rdmult = (int)((double)rdmult * rdc->rd_mult_q_sq_inter_mid_qp); + } else { + rdmult = (int)((double)rdmult * rdc->rd_mult_q_sq_inter_high_qp); + } } else { - if (qindex < 64) - rdmult = rdmult * 4; - else if (qindex <= 128) - rdmult = rdmult * 3 + rdmult / 2; - else if (qindex < 190) - rdmult = rdmult * 4 + rdmult / 2; - else - rdmult = rdmult * 7 + rdmult / 2; + if (qindex < 64) { + rdmult = (int)((double)rdmult * rdc->rd_mult_q_sq_key_ultralow_qp); + } else if (qindex <= 128) { + rdmult = (int)((double)rdmult * rdc->rd_mult_q_sq_key_low_qp); + } else if (qindex < 190) { + rdmult = (int)((double)rdmult * rdc->rd_mult_q_sq_key_mid_qp); + + } else { + rdmult = (int)((double)rdmult * rdc->rd_mult_q_sq_key_high_qp); + } } + #if CONFIG_VP9_HIGHBITDEPTH switch (cpi->common.bit_depth) { case VPX_BITS_10: rdmult = ROUND_POWER_OF_TWO(rdmult, 4); break; diff --git a/vp9/encoder/vp9_rd.h b/vp9/encoder/vp9_rd.h index 4c04c9548..2c9f5e740 100644 --- a/vp9/encoder/vp9_rd.h +++ b/vp9/encoder/vp9_rd.h @@ -101,6 +101,18 @@ typedef enum { THR_INTRA, } THR_MODES_SUB8X8; +typedef struct { + // RD control parameters + // Added for Vizier project. + double rd_mult_q_sq_inter_low_qp; + double rd_mult_q_sq_inter_mid_qp; + double rd_mult_q_sq_inter_high_qp; + double rd_mult_q_sq_key_ultralow_qp; + double rd_mult_q_sq_key_low_qp; + double rd_mult_q_sq_key_mid_qp; + double rd_mult_q_sq_key_high_qp; +} RD_CONTROL; + typedef struct RD_OPT { // Thresh_mult is used to set a threshold for the rd score. A higher value // means that we will accept the best mode so far more often. This number @@ -144,6 +156,8 @@ struct TileDataEnc; struct VP9_COMP; struct macroblock; +void vp9_init_rd_parameters(struct VP9_COMP *cpi); + int vp9_compute_rd_mult_based_on_qindex(const struct VP9_COMP *cpi, int qindex); int vp9_compute_rd_mult(const struct VP9_COMP *cpi, int qindex); |