From d0312379991b81f2aec5a1fa4a50406ca764cdee Mon Sep 17 00:00:00 2001 From: Paul Wilkins Date: Fri, 7 Nov 2014 16:32:50 +0000 Subject: [PATCH] Add variance restriction to AQ2. Add an additional restriction to bit/complexity based segmentation based on spatial variance. Only lower Q when both the number of bits spent in the initial encoding pass and the spatial complexity are below a threshold. This will prevent the low Q segments being used just because there is a surfeit of bits. Small metrics gains especially opsnr. derf ~0.2% std-hd ~0.3% Change-Id: I6a8496d466d673f9b0e2b2ca6304ea7b6d8e1cce --- vp9/encoder/vp9_aq_complexity.c | 15 +++++++++++---- vp9/encoder/vp9_aq_complexity.h | 4 ++-- vp9/encoder/vp9_aq_variance.c | 10 ++++++---- vp9/encoder/vp9_aq_variance.h | 1 + vp9/encoder/vp9_encodeframe.c | 6 +++--- 5 files changed, 23 insertions(+), 13 deletions(-) diff --git a/vp9/encoder/vp9_aq_complexity.c b/vp9/encoder/vp9_aq_complexity.c index f7fca0cde..3762c53d7 100644 --- a/vp9/encoder/vp9_aq_complexity.c +++ b/vp9/encoder/vp9_aq_complexity.c @@ -11,8 +11,9 @@ #include #include +#include "vp9/encoder/vp9_aq_variance.h" +#include "vp9/encoder/vp9_encodeframe.h" #include "vp9/common/vp9_seg_common.h" - #include "vp9/encoder/vp9_segmentation.h" #define AQ_C_SEGMENTS 3 @@ -22,6 +23,7 @@ static const double aq_c_q_adj_factor[AQ_C_STRENGTHS][AQ_C_SEGMENTS] = {{1.0, 1.0, 1.0}, {1.0, 2.0, 1.0}, {1.0, 1.5, 2.5}}; static const double aq_c_transitions[AQ_C_STRENGTHS][AQ_C_SEGMENTS] = {{1.0, 1.0, 1.0}, {1.0, 0.25, 0.0}, {1.0, 0.5, 0.25}}; +static const double aq_c_var_thresholds[AQ_C_SEGMENTS] = {100.0, 12.0, 10.0}; static int get_aq_c_strength(int q_index, vpx_bit_depth_t bit_depth) { // Approximate base quatizer (truncated to int) @@ -94,7 +96,7 @@ void vp9_setup_in_frame_q_adj(VP9_COMP *cpi) { // An "aq_strength" value determines how many segments are supported, // the set of transition points to use and the extent of the quantizer // adjustment for each segment (configured in vp9_setup_in_frame_q_adj()). -void vp9_select_in_frame_q_segment(VP9_COMP *cpi, +void vp9_select_in_frame_q_segment(VP9_COMP *cpi, BLOCK_SIZE bs, int mi_row, int mi_col, int output_enabled, int projected_rate) { VP9_COMMON *const cm = &cpi->common; @@ -118,6 +120,10 @@ void vp9_select_in_frame_q_segment(VP9_COMP *cpi, (bw * bh); const int aq_strength = get_aq_c_strength(cm->base_qindex, cm->bit_depth); const int active_segments = aq_c_active_segments[aq_strength]; + double logvar; + + vp9_setup_src_planes(&cpi->mb, cpi->Source, mi_row, mi_col); + logvar = vp9_log_block_var(cpi, &cpi->mb, bs); // The number of segments considered and the transition points used to // select them is determined by the "aq_strength" value. @@ -127,8 +133,9 @@ void vp9_select_in_frame_q_segment(VP9_COMP *cpi, // with no Q adjustment. segment = active_segments - 1; while (segment > 0) { - if (projected_rate < - (target_rate * aq_c_transitions[aq_strength][segment])) { + if ((projected_rate < + target_rate * aq_c_transitions[aq_strength][segment]) && + (logvar < aq_c_var_thresholds[segment])) { break; } --segment; diff --git a/vp9/encoder/vp9_aq_complexity.h b/vp9/encoder/vp9_aq_complexity.h index af031a46c..6f82aac37 100644 --- a/vp9/encoder/vp9_aq_complexity.h +++ b/vp9/encoder/vp9_aq_complexity.h @@ -19,10 +19,10 @@ extern "C" { struct VP9_COMP; // Select a segment for the current SB64. -void vp9_select_in_frame_q_segment(struct VP9_COMP *cpi, int mi_row, int mi_col, +void vp9_select_in_frame_q_segment(struct VP9_COMP *cpi, BLOCK_SIZE bs, + int mi_row, int mi_col, int output_enabled, int projected_rate); - // This function sets up a set of segments with delta Q values around // the baseline frame quantizer. void vp9_setup_in_frame_q_adj(struct VP9_COMP *cpi); diff --git a/vp9/encoder/vp9_aq_variance.c b/vp9/encoder/vp9_aq_variance.c index fbf3cff09..df65696b1 100644 --- a/vp9/encoder/vp9_aq_variance.c +++ b/vp9/encoder/vp9_aq_variance.c @@ -126,12 +126,14 @@ static unsigned int block_variance(VP9_COMP *cpi, MACROBLOCK *x, } } -int vp9_block_energy(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs) { - double energy; +double vp9_log_block_var(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs) { unsigned int var = block_variance(cpi, x, bs); - vp9_clear_system_state(); + return log(var + 1.0); +} - energy = 0.9 * (log(var + 1.0) - 10.0); +int vp9_block_energy(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs) { + double energy; + energy = 0.9 * (vp9_log_block_var(cpi, x, bs) - 10.0); return clamp((int)round(energy), ENERGY_MIN, ENERGY_MAX); } diff --git a/vp9/encoder/vp9_aq_variance.h b/vp9/encoder/vp9_aq_variance.h index ac144fb32..a0effa311 100644 --- a/vp9/encoder/vp9_aq_variance.h +++ b/vp9/encoder/vp9_aq_variance.h @@ -22,6 +22,7 @@ unsigned int vp9_vaq_segment_id(int energy); void vp9_vaq_frame_setup(VP9_COMP *cpi); int vp9_block_energy(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs); +double vp9_log_block_var(VP9_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bs); #ifdef __cplusplus } // extern "C" diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index 93e85292a..7ab240b01 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -1699,7 +1699,7 @@ static void rd_use_partition(VP9_COMP *cpi, // and and if necessary apply a Q delta using segmentation to get // closer to the target. if ((cpi->oxcf.aq_mode == COMPLEXITY_AQ) && cm->seg.update_map) { - vp9_select_in_frame_q_segment(cpi, mi_row, mi_col, + vp9_select_in_frame_q_segment(cpi, bsize, mi_row, mi_col, output_enabled, chosen_rdc.rate); } encode_sb(cpi, tile_info, tp, mi_row, mi_col, output_enabled, bsize, @@ -2438,7 +2438,7 @@ static void rd_pick_partition(VP9_COMP *cpi, // and and if necessary apply a Q delta using segmentation to get // closer to the target. if ((cpi->oxcf.aq_mode == COMPLEXITY_AQ) && cm->seg.update_map) - vp9_select_in_frame_q_segment(cpi, mi_row, mi_col, output_enabled, + vp9_select_in_frame_q_segment(cpi, bsize, mi_row, mi_col, output_enabled, best_rdc.rate); encode_sb(cpi, tile_info, tp, mi_row, mi_col, output_enabled, bsize, pc_tree); @@ -2943,7 +2943,7 @@ static void nonrd_pick_partition(VP9_COMP *cpi, // and and if necessary apply a Q delta using segmentation to get // closer to the target. if ((oxcf->aq_mode == COMPLEXITY_AQ) && cm->seg.update_map) { - vp9_select_in_frame_q_segment(cpi, mi_row, mi_col, output_enabled, + vp9_select_in_frame_q_segment(cpi, bsize, mi_row, mi_col, output_enabled, best_rdc.rate); } encode_sb_rt(cpi, tile_info, tp, mi_row, mi_col, output_enabled, -- 2.40.0