From f30b323180c3c358b646414f79f33da5664eeccb Mon Sep 17 00:00:00 2001 From: Paul Wilkins Date: Mon, 3 Feb 2014 12:47:01 +0000 Subject: [PATCH] Modified Aq1 and Aq2 Aq 1 only updates segment map on kf and arf and only uses 3 segments. With these settings AQ1 is + for most clips in SSIM but negative in psnr. However, the penalty in PSNR is much less than previously. Old version aq1 average results for std hd -20.899% psnr, -5.809% SSIM New version aq1 for std hd -3.57% psnr, +1.23% SSIM Aq2 Now uses only 2 segments and rd. This mode is still slightly negative for most clips on psnr and SSIM but seems to have a much bigger visual impact on several problem clips than aq mode 1. Old results for std hd: -2.578% psnr, -1.151% SSIM New results for std hd: -1.561% psnr, -0.85% SSIM Change-Id: I94f57f8a73121629ce598fb921aad761c1450e1c --- vp9/encoder/vp9_encodeframe.c | 25 ++++++++++++++++++------ vp9/encoder/vp9_onyx_if.c | 8 ++++---- vp9/encoder/vp9_vaq.c | 44 +++++++++++++++++++++++-------------------- 3 files changed, 47 insertions(+), 30 deletions(-) diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index e895d0a..d189da0 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -365,8 +365,6 @@ static void select_in_frame_q_segment(VP9_COMP *cpi, target_rate = (cpi->rc.sb64_target_rate * xmis * ymis * 256) / (bw * bh); if (projected_rate < (target_rate / 4)) { - segment = 2; - } else if (projected_rate < (target_rate / 2)) { segment = 1; } else { segment = 0; @@ -667,7 +665,18 @@ static void rd_pick_sb_modes(VP9_COMP *cpi, const TileInfo *const tile, if (cpi->oxcf.aq_mode == VARIANCE_AQ) { const int energy = bsize <= BLOCK_16X16 ? x->mb_energy : vp9_block_energy(cpi, x, bsize); - xd->mi_8x8[0]->mbmi.segment_id = vp9_vaq_segment_id(energy); + + if (cm->frame_type == KEY_FRAME || + cpi->refresh_alt_ref_frame || + (cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref)) { + xd->mi_8x8[0]->mbmi.segment_id = vp9_vaq_segment_id(energy); + } else { + const uint8_t *const map = cm->seg.update_map ? cpi->segmentation_map + : cm->last_frame_seg_map; + xd->mi_8x8[0]->mbmi.segment_id = + vp9_get_segment_id(cm, map, bsize, mi_row, mi_col); + } + rdmult_ratio = vp9_vaq_rdmult_ratio(energy); vp9_mb_init_quantizer(cpi, x); } @@ -681,11 +690,12 @@ static void rd_pick_sb_modes(VP9_COMP *cpi, const TileInfo *const tile, } else if (cpi->oxcf.aq_mode == COMPLEXITY_AQ) { const int mi_offset = mi_row * cm->mi_cols + mi_col; unsigned char complexity = cpi->complexity_map[mi_offset]; - const int is_edge = (mi_row == 0) || (mi_row == (cm->mi_rows - 1)) || - (mi_col == 0) || (mi_col == (cm->mi_cols - 1)); + const int is_edge = (mi_row <= 1) || (mi_row >= (cm->mi_rows - 2)) || + (mi_col <= 1) || (mi_col >= (cm->mi_cols - 2)); - if (!is_edge && (complexity > 128)) + if (!is_edge && (complexity > 128)) { x->rdmult = x->rdmult + ((x->rdmult * (complexity - 128)) / 256); + } } // Find best coding mode & reconstruct the MB so it is available @@ -709,6 +719,9 @@ static void rd_pick_sb_modes(VP9_COMP *cpi, const TileInfo *const tile, *totalrate = round(*totalrate * rdmult_ratio); } } + else if (cpi->oxcf.aq_mode == COMPLEXITY_AQ) { + x->rdmult = orig_rdmult; + } } static void update_stats(VP9_COMP *cpi) { diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index b4972be..389b8be 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -96,7 +96,7 @@ FILE *keyfile; void vp9_init_quantizer(VP9_COMP *cpi); static const double in_frame_q_adj_ratio[MAX_SEGMENTS] = - {1.0, 1.5, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0}; + {1.0, 2.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}; static INLINE void Scale2Ratio(int mode, int *hr, int *hs) { switch (mode) { @@ -267,7 +267,6 @@ static void setup_in_frame_q_adj(VP9_COMP *cpi) { // Clear down the complexity map used for rd vpx_memset(cpi->complexity_map, 0, cm->mi_rows * cm->mi_cols); - // Enable segmentation vp9_enable_segmentation((VP9_PTR)cpi); vp9_clearall_segfeatures(seg); @@ -278,7 +277,7 @@ static void setup_in_frame_q_adj(VP9_COMP *cpi) { vp9_disable_segfeature(seg, 0, SEG_LVL_ALT_Q); // Use some of the segments for in frame Q adjustment - for (segment = 1; segment < 3; segment++) { + for (segment = 1; segment < 2; segment++) { qindex_delta = vp9_compute_qdelta_by_rate(cpi, cm->base_qindex, in_frame_q_adj_ratio[segment]); @@ -3553,8 +3552,9 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags, xd->interp_kernel = vp9_get_interp_kernel( DEFAULT_INTERP_FILTER == SWITCHABLE ? EIGHTTAP : DEFAULT_INTERP_FILTER); - if (cpi->oxcf.aq_mode == VARIANCE_AQ) + if (cpi->oxcf.aq_mode == VARIANCE_AQ) { vp9_vaq_init(); + } if (cpi->use_svc) { SvcEncode(cpi, size, dest, frame_flags); diff --git a/vp9/encoder/vp9_vaq.c b/vp9/encoder/vp9_vaq.c index 1f9cb87..acd7c41 100644 --- a/vp9/encoder/vp9_vaq.c +++ b/vp9/encoder/vp9_vaq.c @@ -19,8 +19,8 @@ #include "vp9/encoder/vp9_segmentation.h" #include "vp9/common/vp9_systemdependent.h" -#define ENERGY_MIN (-3) -#define ENERGY_MAX (3) +#define ENERGY_MIN (-1) +#define ENERGY_MAX (1) #define ENERGY_SPAN (ENERGY_MAX - ENERGY_MIN + 1) #define ENERGY_IN_BOUNDS(energy)\ assert((energy) >= ENERGY_MIN && (energy) <= ENERGY_MAX) @@ -65,7 +65,7 @@ void vp9_vaq_init() { vp9_clear_system_state(); // __asm emms; - base_ratio = 1.8; + base_ratio = 1.5; for (i = ENERGY_MIN; i <= ENERGY_MAX; i++) { Q_RATIO(i) = pow(base_ratio, i/3.0); @@ -80,30 +80,34 @@ void vp9_vaq_frame_setup(VP9_COMP *cpi) { cm->y_dc_delta_q); int i; - vp9_enable_segmentation((VP9_PTR)cpi); - vp9_clearall_segfeatures(seg); + if (cm->frame_type == KEY_FRAME || + cpi->refresh_alt_ref_frame || + (cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref)) { + vp9_enable_segmentation((VP9_PTR)cpi); + vp9_clearall_segfeatures(seg); - seg->abs_delta = SEGMENT_DELTADATA; + seg->abs_delta = SEGMENT_DELTADATA; - vp9_clear_system_state(); // __asm emms; + vp9_clear_system_state(); // __asm emms; - for (i = ENERGY_MIN; i <= ENERGY_MAX; i++) { - int qindex_delta, segment_rdmult; + for (i = ENERGY_MIN; i <= ENERGY_MAX; i++) { + int qindex_delta, segment_rdmult; - if (Q_RATIO(i) == 1) { - // No need to enable SEG_LVL_ALT_Q for this segment - RDMULT_RATIO(i) = 1; - continue; - } + if (Q_RATIO(i) == 1) { + // No need to enable SEG_LVL_ALT_Q for this segment + RDMULT_RATIO(i) = 1; + continue; + } - qindex_delta = vp9_compute_qdelta(cpi, base_q, base_q * Q_RATIO(i)); - vp9_set_segdata(seg, SEGMENT_ID(i), SEG_LVL_ALT_Q, qindex_delta); - vp9_enable_segfeature(seg, SEGMENT_ID(i), SEG_LVL_ALT_Q); + qindex_delta = vp9_compute_qdelta(cpi, base_q, base_q * Q_RATIO(i)); + vp9_set_segdata(seg, SEGMENT_ID(i), SEG_LVL_ALT_Q, qindex_delta); + vp9_enable_segfeature(seg, SEGMENT_ID(i), SEG_LVL_ALT_Q); - segment_rdmult = vp9_compute_rd_mult(cpi, cm->base_qindex + qindex_delta + - cm->y_dc_delta_q); + segment_rdmult = vp9_compute_rd_mult(cpi, cm->base_qindex + qindex_delta + + cm->y_dc_delta_q); - RDMULT_RATIO(i) = (double) segment_rdmult / base_rdmult; + RDMULT_RATIO(i) = (double) segment_rdmult / base_rdmult; + } } } -- 2.7.4