From d3aaac367bd716b2db06e774f0a8eea7768dd184 Mon Sep 17 00:00:00 2001 From: Paul Wilkins Date: Wed, 31 Mar 2021 16:58:51 +0100 Subject: [PATCH] Change calculation of rd multiplier. Change the way the rd multiplier is adjusted for Q and frame type. Previously in VP9 the rd multiplier was adjusted based on crude Q bins and whether the frame was a key frame or inter frame. The Q bins create some problems as they potentially introduce discontinuities in the RD curve. For example, rate rising with a stepwise increase in Q instead of falling. As such, in AV1 they have been removed. A further issue was identified when examining the first round of results from from the Vizier project. Here the multiplier for each Q bin and each frame type was optimized for a training set, for various video formats, using single point encodes at the appropriate YT rates. These initial results appeared to show a trend for increased rd multiplier at higher Q for key frames. This fits with intuition as in this encoding context a higher Q indicates that a clip is harder to encode and frames less well predicted. However, the situation appeared to reverse for inter frames with higher rd multipliers chosen at low Q. My initial suspicion was that this was a result of over fitting, but on closer analysis I realized that this may be more related to frame type within the broader inter frame classification. Specifically frames coded at low Q are predominantly ARF frames, for the mid Q bin there will likely be a mix of ARF and normal inter frames, and for the high Q bin the frames will almost exclusively be normal inter frames from difficult content. ARF frames are inherently less well predicted than other inter frames being further apart and not having access to as many prediction modes. We also know from previous work that ARF frames have a higher incidence of INTRA coding and may well behave more like key frames in this context. This patch replaces the bin based approach with a linear function that applies a small but smooth Q based adjustment. It also splits ARF frames and normal inter frames into separate categories. With this done number of parameters that will be exposed for the next round of Vizier training is reduced from 7 to 3 (one adjustment factor each for inter, ARF and key frames) This patch gives net BDATE gains for our test sets even with the baseline / default factors as follows: (% BDRATE change in overall PSNR and SSIM, -ve is better) LowRes -0.231, -0.050 ugc360p 0.160, -0.315 midres2 -0.348, -1.170 hdres2 -0.407, -0.691 Change-Id: I46dd2fea77b1c2849c122f10fd0df74bbd3fcc7f --- vp9/encoder/vp9_rd.c | 114 +++++++++++++++++++++------------------------------ vp9/encoder/vp9_rd.h | 10 ++--- 2 files changed, 50 insertions(+), 74 deletions(-) diff --git a/vp9/encoder/vp9_rd.c b/vp9/encoder/vp9_rd.c index d3bf3d6..9efd742 100644 --- a/vp9/encoder/vp9_rd.c +++ b/vp9/encoder/vp9_rd.c @@ -205,62 +205,36 @@ void vp9_init_rd_parameters(VP9_COMP *cpi) { // Make sure this function is floating point safe. vpx_clear_system_state(); - rdc->rd_mult_key_high_qp_fac = 1.0; // Default: no Vizer values yet + rdc->rd_mult_arf_qp_fac = 1.0; // Default: No Vizier values yet + // These hard wired estimates for the Vizier values will be removed later + // as the per format factors will be set on the command line. if (0) { unsigned int screen_area = (cpi->common.width * cpi->common.height); if (screen_area <= 176 * 144) { - rdc->rd_mult_inter_low_qp_fac = 1.018; - rdc->rd_mult_inter_mid_qp_fac = 0.896; - rdc->rd_mult_inter_high_qp_fac = 1.432; - rdc->rd_mult_key_ultralow_qp_fac = 1.073; - rdc->rd_mult_key_low_qp_fac = 1.630; - rdc->rd_mult_key_mid_qp_fac = 1.050; + rdc->rd_mult_inter_qp_fac = 0.896; + rdc->rd_mult_key_qp_fac = 1.050; } else if (screen_area <= 320 * 240) { - rdc->rd_mult_inter_low_qp_fac = 1.127; - rdc->rd_mult_inter_mid_qp_fac = 0.998; - rdc->rd_mult_inter_high_qp_fac = 1.463; - rdc->rd_mult_key_ultralow_qp_fac = 1.054; - rdc->rd_mult_key_low_qp_fac = 1.285; - rdc->rd_mult_key_mid_qp_fac = 0.952; + rdc->rd_mult_inter_qp_fac = 0.998; + rdc->rd_mult_key_qp_fac = 0.952; } else if (screen_area <= 640 * 360) { - rdc->rd_mult_inter_low_qp_fac = 1.183; - rdc->rd_mult_inter_mid_qp_fac = 0.959; - rdc->rd_mult_inter_high_qp_fac = 1.457; - rdc->rd_mult_key_ultralow_qp_fac = 1.144; - rdc->rd_mult_key_low_qp_fac = 1.734; - rdc->rd_mult_key_mid_qp_fac = 1.071; + rdc->rd_mult_inter_qp_fac = 0.959; + rdc->rd_mult_key_qp_fac = 1.071; } else if (screen_area <= 854 * 480) { - rdc->rd_mult_inter_low_qp_fac = 1.203; - rdc->rd_mult_inter_mid_qp_fac = 1.027; - rdc->rd_mult_inter_high_qp_fac = 1.027; - rdc->rd_mult_key_ultralow_qp_fac = 1.246; - rdc->rd_mult_key_low_qp_fac = 1.246; - rdc->rd_mult_key_mid_qp_fac = 1.280; + rdc->rd_mult_inter_qp_fac = 1.027; + rdc->rd_mult_key_qp_fac = 1.280; } else if (screen_area <= 1280 * 720) { - rdc->rd_mult_inter_low_qp_fac = 1.280; - rdc->rd_mult_inter_mid_qp_fac = 1.004; - rdc->rd_mult_inter_high_qp_fac = 1.470; - rdc->rd_mult_key_ultralow_qp_fac = 0.987; - rdc->rd_mult_key_low_qp_fac = 1.671; - rdc->rd_mult_key_mid_qp_fac = 1.193; + rdc->rd_mult_inter_qp_fac = 1.004; + rdc->rd_mult_key_qp_fac = 1.193; } else { - rdc->rd_mult_inter_low_qp_fac = 1.50; - rdc->rd_mult_inter_mid_qp_fac = 0.874; - rdc->rd_mult_inter_high_qp_fac = 1.07; - rdc->rd_mult_key_ultralow_qp_fac = 1.1; - rdc->rd_mult_key_low_qp_fac = 2.35; - rdc->rd_mult_key_mid_qp_fac = 0.837; + rdc->rd_mult_inter_qp_fac = 0.874; + rdc->rd_mult_key_qp_fac = 0.837; } } else { // For now force defaults unless testing - rdc->rd_mult_inter_low_qp_fac = 1.0; - rdc->rd_mult_inter_mid_qp_fac = 1.0; - rdc->rd_mult_inter_high_qp_fac = 1.0; - rdc->rd_mult_key_ultralow_qp_fac = 1.0; - rdc->rd_mult_key_low_qp_fac = 1.0; - rdc->rd_mult_key_mid_qp_fac = 1.0; + rdc->rd_mult_inter_qp_fac = 1.0; + rdc->rd_mult_key_qp_fac = 1.0; } } @@ -273,6 +247,27 @@ void vp9_init_rd_parameters(VP9_COMP *cpi) { #define KEY_MID_QP_RDM 4.5 #define KEY_HIGH_QP_RDM 7.5 +// Returns the default rd multiplier for inter frames for a given qindex. +// The function here is a first pass estimate based on data from +// a previous Vizer run +static double def_inter_rd_multiplier(int qindex) { + return 4.15 + (0.001 * (double)qindex); +} + +// Returns the default rd multiplier for ARF/Golden Frames for a given qindex. +// The function here is a first pass estimate based on data from +// a previous Vizer run +static double def_arf_rd_multiplier(int qindex) { + return 4.25 + (0.001 * (double)qindex); +} + +// Returns the default rd multiplier for key frames for a given qindex. +// The function here is a first pass estimate based on data from +// a previous Vizer run +static double def_kf_rd_multiplier(int qindex) { + return 4.35 + (0.001 * (double)qindex); +} + int vp9_compute_rd_mult_based_on_qindex(const VP9_COMP *cpi, int qindex) { const RD_CONTROL *rdc = &cpi->rd_ctrl; const int q = vp9_dc_quant(qindex, 0, cpi->common.bit_depth); @@ -282,31 +277,16 @@ int vp9_compute_rd_mult_based_on_qindex(const VP9_COMP *cpi, int qindex) { // Make sure this function is floating point safe. vpx_clear_system_state(); - if (cpi->common.frame_type != KEY_FRAME) { - if (qindex < 128) { - rdmult = (int)((double)rdmult * INTER_LOW_QP_RDM * - rdc->rd_mult_inter_low_qp_fac); - } else if (qindex < 190) { - rdmult = (int)((double)rdmult * INTER_MID_QP_RDM * - rdc->rd_mult_inter_mid_qp_fac); - } else { - rdmult = (int)((double)rdmult * INTER_HIGH_QP_RDM * - rdc->rd_mult_inter_high_qp_fac); - } + if (cpi->common.frame_type == KEY_FRAME) { + double def_rd_q_mult = def_kf_rd_multiplier(qindex); + rdmult = (int)((double)rdmult * def_rd_q_mult * rdc->rd_mult_key_qp_fac); + } else if (!cpi->rc.is_src_frame_alt_ref && + (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) { + double def_rd_q_mult = def_arf_rd_multiplier(qindex); + rdmult = (int)((double)rdmult * def_rd_q_mult * rdc->rd_mult_arf_qp_fac); } else { - if (qindex < 64) { - rdmult = (int)((double)rdmult * KEY_ULOW_QP_RDM * - rdc->rd_mult_key_ultralow_qp_fac); - } else if (qindex <= 128) { - rdmult = - (int)((double)rdmult * KEY_LOW_QP_RDM * rdc->rd_mult_key_low_qp_fac); - } else if (qindex < 190) { - rdmult = - (int)((double)rdmult * KEY_MID_QP_RDM * rdc->rd_mult_key_mid_qp_fac); - } else { - rdmult = (int)((double)rdmult * KEY_HIGH_QP_RDM * - rdc->rd_mult_key_high_qp_fac); - } + double def_rd_q_mult = def_inter_rd_multiplier(qindex); + rdmult = (int)((double)rdmult * def_rd_q_mult * rdc->rd_mult_inter_qp_fac); } #if CONFIG_VP9_HIGHBITDEPTH diff --git a/vp9/encoder/vp9_rd.h b/vp9/encoder/vp9_rd.h index 4899e1a..d2bc5e6 100644 --- a/vp9/encoder/vp9_rd.h +++ b/vp9/encoder/vp9_rd.h @@ -103,13 +103,9 @@ typedef enum { typedef struct { // RD multiplier control factors added for Vizier project. - double rd_mult_inter_low_qp_fac; - double rd_mult_inter_mid_qp_fac; - double rd_mult_inter_high_qp_fac; - double rd_mult_key_ultralow_qp_fac; - double rd_mult_key_low_qp_fac; - double rd_mult_key_mid_qp_fac; - double rd_mult_key_high_qp_fac; + double rd_mult_inter_qp_fac; + double rd_mult_arf_qp_fac; + double rd_mult_key_qp_fac; } RD_CONTROL; typedef struct RD_OPT { -- 2.7.4