From c8338ebf7acba1f0a2d0d182b643c5c14417e33a Mon Sep 17 00:00:00 2001 From: Paul Wilkins Date: Fri, 14 Jan 2011 11:34:53 +0000 Subject: [PATCH 1/4] KF/GF Pulsing This change is designed to try and reduce pulsing effects when moving with a complex transition like a fade, into an easy or static section in an otherwise difficult clip in CQ mode. The active CQ level is relaxed down to the user entered level for frames that are generating less than the passed in minimum bandwidth. Change-Id: Id6d8b551daad4f489c087bd742bc95418a95f3f0 --- vp8/encoder/onyx_if.c | 45 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index 470a9ac84..e0d1d7043 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -2029,7 +2029,7 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf) cpi->buffered_mode = (cpi->oxcf.optimal_buffer_level > 0) ? TRUE : FALSE; // Experimental cq target value - cpi->cq_target_quality = oxcf->cq_level; + cpi->cq_target_quality = cpi->oxcf.cq_level; cpi->rolling_target_bits = cpi->av_per_frame_bandwidth; cpi->rolling_actual_bits = cpi->av_per_frame_bandwidth; @@ -3519,14 +3519,29 @@ static BOOL recode_loop_test( VP8_COMP *cpi, { // General over and under shoot tests if ( ((cpi->projected_frame_size > high_limit) && (q < maxq)) || - ((cpi->projected_frame_size < low_limit) && (q > minq)) || - ((cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) && - (q > cpi->cq_target_quality) && - (cpi->projected_frame_size < - ((cpi->this_frame_target * 7) >> 3))) ) + ((cpi->projected_frame_size < low_limit) && (q > minq)) ) { force_recode = TRUE; } + // Special Constrained quality tests + else if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) + { + // Undershoot and below auto cq level + if ( (q > cpi->cq_target_quality) && + (cpi->projected_frame_size < + ((cpi->this_frame_target * 7) >> 3))) + { + force_recode = TRUE; + } + // Severe undershoot and between auto and user cq level + else if ( (q > cpi->oxcf.cq_level) && + (cpi->projected_frame_size < cpi->min_frame_bandwidth) && + (cpi->active_best_quality > cpi->oxcf.cq_level)) + { + force_recode = TRUE; + cpi->active_best_quality = cpi->oxcf.cq_level; + } + } } return force_recode; @@ -3853,7 +3868,13 @@ static void encode_frame_to_data_rate if ((cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) && (cpi->active_best_quality < cpi->cq_target_quality) ) { - cpi->active_best_quality = cpi->cq_target_quality; + // If we are strongly undershooting the target rate in the last + // frames then use the user passed in cq value not the auto + // cq value. + if ( cpi->rolling_actual_bits < cpi->min_frame_bandwidth ) + cpi->active_best_quality = cpi->oxcf.cq_level; + else + cpi->active_best_quality = cpi->cq_target_quality; } } @@ -4219,6 +4240,16 @@ static void encode_frame_to_data_rate Q = vp8_regulate_q(cpi, cpi->this_frame_target); + // Special case reset for qlow for constrained quality. + // This should only trigger where there is very substantial + // undershoot on a frame and the auto cq level is above + // the user passsed in value. + if ( (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) && + (Q < q_low) ) + { + q_low = Q; + } + while (((Q > q_high) || (cpi->zbin_over_quant > zbin_oq_high)) && (Retries < 10)) { vp8_update_rate_correction_factors(cpi, 0); From 72e22b0bb8d66c37d57bccb95c9c43660e080745 Mon Sep 17 00:00:00 2001 From: Paul Wilkins Date: Fri, 14 Jan 2011 12:07:12 +0000 Subject: [PATCH 2/4] Experimental change to help with ARNR problem. Allow use of other reference frames for the ARF overlay frame when ARNR filtering is enabled Change-Id: Icd6a9fb38977a88fbe7cc9b9c18198eb454c0273 --- vp8/encoder/rdopt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/vp8/encoder/rdopt.c b/vp8/encoder/rdopt.c index bab7ca12d..8598fc6ea 100644 --- a/vp8/encoder/rdopt.c +++ b/vp8/encoder/rdopt.c @@ -1849,7 +1849,10 @@ int vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED; x->e_mbd.mode_info_context->mbmi.ref_frame = vp8_ref_frame_order[mode_index]; - //Only consider ZEROMV/ALTREF_FRAME for alt ref frame. + // Only consider ZEROMV/ALTREF_FRAME for alt ref frame, + // unless ARNR filtering is enabled in which case we want + // an unfiltered alternative + //if (cpi->is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames > 0)) if (cpi->is_src_frame_alt_ref) { if (this_mode != ZEROMV || x->e_mbd.mode_info_context->mbmi.ref_frame != ALTREF_FRAME) From 2c1b06e67213d5e7375d911f326810dbf086f9e6 Mon Sep 17 00:00:00 2001 From: Adrian Grange Date: Fri, 14 Jan 2011 15:04:39 +0000 Subject: [PATCH 3/4] ARNR filter pointer update bug fix In cases where the frame width is not a multiple of 16 the ARNR filter would go wrong. In vp8_temporal_filter_iterate_c when updating pointers at the end of a row of MBs, the image size was incorrectly used rather than using Num_MBs_In_Row times 16 (Y) or 8 (U,V). This worked when width is multiple of 16 but failed otherwise. Change-Id: I008919062715bd3d17c7aa2562ab58d1cb37053a --- vp8/encoder/temporal_filter.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/vp8/encoder/temporal_filter.c b/vp8/encoder/temporal_filter.c index 396e3390d..f28daaff9 100644 --- a/vp8/encoder/temporal_filter.c +++ b/vp8/encoder/temporal_filter.c @@ -290,8 +290,8 @@ static void vp8_temporal_filter_iterate_c int mb_col, mb_row; unsigned int filter_weight[MAX_LAG_BUFFERS]; unsigned char *mm_ptr = cpi->fp_motion_map; - int cols = cpi->common.mb_cols; - int rows = cpi->common.mb_rows; + int mb_cols = cpi->common.mb_cols; + int mb_rows = cpi->common.mb_rows; int MBs = cpi->common.MBs; int mb_y_offset = 0; int mb_uv_offset = 0; @@ -314,7 +314,7 @@ static void vp8_temporal_filter_iterate_c filter_weight[frame] = 1; } - for (mb_row = 0; mb_row < rows; mb_row++) + for (mb_row = 0; mb_row < mb_rows; mb_row++) { #if ALT_REF_MC_ENABLED // Reduced search extent by 3 for 6-tap filter & smaller UMV border @@ -323,7 +323,7 @@ static void vp8_temporal_filter_iterate_c + (VP8BORDERINPIXELS - 19); #endif - for (mb_col = 0; mb_col < cols; mb_col++) + for (mb_col = 0; mb_col < mb_cols; mb_col++) { int i, j, k, w; int weight_cap; @@ -497,8 +497,8 @@ static void vp8_temporal_filter_iterate_c mb_uv_offset += 8; } - mb_y_offset += 16*f->y_stride-f->y_width; - mb_uv_offset += 8*f->uv_stride-f->uv_width; + mb_y_offset += 16*(f->y_stride-mb_cols); + mb_uv_offset += 8*(f->uv_stride-mb_cols); } // Restore input state From 415371c9d99639258e9e4546bda45fe889a79ef3 Mon Sep 17 00:00:00 2001 From: Paul Wilkins Date: Fri, 14 Jan 2011 14:52:15 +0000 Subject: [PATCH 4/4] Testing of modes with Alt Ref frame Previously when a frame was being overlaid on a previously coded alt ref frame we only checked the alt ref 0,0 mode. Where there is a possibility that the alt ref buffer is a filtered frame we should allow the other prediction modes as normal or at the least allow use of the last frame buffer. Change-Id: I4d6227223d125c96b4f3066ec6ec9484fee7768c --- vp8/encoder/pickinter.c | 6 ++++-- vp8/encoder/rdopt.c | 3 +-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/vp8/encoder/pickinter.c b/vp8/encoder/pickinter.c index 8dfca351c..2b0f57508 100644 --- a/vp8/encoder/pickinter.c +++ b/vp8/encoder/pickinter.c @@ -608,8 +608,10 @@ int vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int rec memcpy(mdcounts, MDCounts[x->e_mbd.mode_info_context->mbmi.ref_frame], sizeof(mdcounts)); } - //Only consider ZEROMV/ALTREF_FRAME for alt ref frame. - if (cpi->is_src_frame_alt_ref) + // Only consider ZEROMV/ALTREF_FRAME for alt ref frame, + // unless ARNR filtering is enabled in which case we want + // an unfiltered alternative + if (cpi->is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0)) { if (this_mode != ZEROMV || x->e_mbd.mode_info_context->mbmi.ref_frame != ALTREF_FRAME) continue; diff --git a/vp8/encoder/rdopt.c b/vp8/encoder/rdopt.c index 8598fc6ea..b2a3e117f 100644 --- a/vp8/encoder/rdopt.c +++ b/vp8/encoder/rdopt.c @@ -1852,8 +1852,7 @@ int vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int // Only consider ZEROMV/ALTREF_FRAME for alt ref frame, // unless ARNR filtering is enabled in which case we want // an unfiltered alternative - //if (cpi->is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames > 0)) - if (cpi->is_src_frame_alt_ref) + if (cpi->is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0)) { if (this_mode != ZEROMV || x->e_mbd.mode_info_context->mbmi.ref_frame != ALTREF_FRAME) continue;