From f2ec452fbc8779fc2230148d7b446cc84929ff70 Mon Sep 17 00:00:00 2001 From: Paul Wilkins Date: Wed, 11 Apr 2012 14:37:48 +0100 Subject: [PATCH] Changes to costing of skip. Update the costing of skip in the recode loop and rd code. Change-Id: I2e5ebbd7ddf201212b32441321e12626cd0423e9 --- vp8/encoder/bitstream.c | 98 ++++++++++++++++++++++++------------------ vp8/encoder/onyx_if.c | 84 ++++++++++++++++++++++++++---------- vp8/encoder/rdopt.c | 111 +++++++++++++++++++++++++++++------------------- 3 files changed, 186 insertions(+), 107 deletions(-) diff --git a/vp8/encoder/bitstream.c b/vp8/encoder/bitstream.c index 1ee6653..065ea9f 100644 --- a/vp8/encoder/bitstream.c +++ b/vp8/encoder/bitstream.c @@ -120,6 +120,56 @@ static void update_mbintra_mode_probs(VP8_COMP *cpi) } } +void update_skip_probs(VP8_COMP *cpi) +{ +#if CONFIG_NEWENTROPY + VP8_COMMON *const pc = & cpi->common; + int prob_skip_false[3] = {0, 0, 0}; + int k; + + for (k=0;kskip_false_count[k] + cpi->skip_true_count[k]) ) + { + prob_skip_false[k] = + cpi->skip_false_count[k] * 256 / + (cpi->skip_false_count[k] + cpi->skip_true_count[k]); + + if (prob_skip_false[k] <= 1) + prob_skip_false[k] = 1; + + if (prob_skip_false[k] > 255) + prob_skip_false[k] = 255; + } + else + prob_skip_false[k] = 128; + + pc->mbskip_pred_probs[k] = prob_skip_false[k]; + vp8_write_literal(w, prob_skip_false[k], 8); + } + +#else + int prob_skip_false = 0; + + if ( (cpi->skip_false_count + cpi->skip_true_count) ) + { + prob_skip_false = cpi->skip_false_count * 256 / + (cpi->skip_false_count + cpi->skip_true_count); + + if (prob_skip_false <= 1) + prob_skip_false = 1; + + if (prob_skip_false > 255) + prob_skip_false = 255; + } + else + prob_skip_false = 128; + + cpi->prob_skip_false = prob_skip_false; + +#endif +} + static void write_ymode(vp8_writer *bc, int m, const vp8_prob *p) { vp8_write_token(bc, vp8_ymode_tree, p, vp8_ymode_encodings + m); @@ -592,12 +642,6 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) int mb_row, mb_col; int row, col; -#if CONFIG_NEWENTROPY - int prob_skip_false[3] = {0, 0, 0}; -#else - int prob_skip_false = 0; -#endif - // Values used in prediction model coding vp8_prob pred_prob; unsigned char prediction_flag; @@ -616,45 +660,15 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) if (pc->mb_no_coeff_skip) { - // Divide by 0 check. 0 case possible with segment features #if CONFIG_NEWENTROPY int k; - for (k=0;kskip_false_count[k] + cpi->skip_true_count[k]) ) - { - prob_skip_false[k] = cpi->skip_false_count[k] * 256 / - (cpi->skip_false_count[k] + cpi->skip_true_count[k]); - - if (prob_skip_false[k] <= 1) - prob_skip_false[k] = 1; - - if (prob_skip_false[k] > 255) - prob_skip_false[k] = 255; - } - else - prob_skip_false[k] = 255; - pc->mbskip_pred_probs[k] = prob_skip_false[k]; - vp8_write_literal(w, prob_skip_false[k], 8); - } + update_skip_probs( cpi ); + for (k=0;kprob_skip_false[k], 8); #else - if ( (cpi->skip_false_count + cpi->skip_true_count) ) - { - prob_skip_false = cpi->skip_false_count * 256 / - (cpi->skip_false_count + cpi->skip_true_count); - - if (prob_skip_false <= 1) - prob_skip_false = 1; - - if (prob_skip_false > 255) - prob_skip_false = 255; - } - else - prob_skip_false = 255; - - cpi->prob_skip_false = prob_skip_false; - vp8_write_literal(w, prob_skip_false, 8); + update_skip_probs( cpi ); + vp8_write_literal(w, cpi->prob_skip_false, 8); #endif } @@ -783,7 +797,7 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) vp8_encode_bool(w, mi->mb_skip_coeff, get_pred_prob(pc, xd, PRED_MBSKIP)); #else - vp8_encode_bool(w, mi->mb_skip_coeff, prob_skip_false); + vp8_encode_bool(w, mi->mb_skip_coeff, cpi->prob_skip_false); #endif } diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index 117d3bd..a758b19 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -292,6 +292,59 @@ void init_base_skip_probs() #endif } } +void update_base_skip_probs(VP8_COMP *cpi) +{ + VP8_COMMON *cm = &cpi->common; + + if (cm->frame_type != KEY_FRAME) + { + update_skip_probs(cpi); + + if (cm->refresh_alt_ref_frame) + { +#if CONFIG_NEWENTROPY + int k; + for (k=0; klast_skip_false_probs[2][k] = cm->mbskip_pred_probs[k]; +#else + cpi->last_skip_false_probs[2] = cpi->prob_skip_false; +#endif + cpi->last_skip_probs_q[2] = cm->base_qindex; + } + else if (cpi->common.refresh_golden_frame) + { +#if CONFIG_NEWENTROPY + int k; + for (k=0; klast_skip_false_probs[1][k] = cm->mbskip_pred_probs[k]; +#else + cpi->last_skip_false_probs[1] = cpi->prob_skip_false; +#endif + cpi->last_skip_probs_q[1] = cm->base_qindex; + } + else + { +#if CONFIG_NEWENTROPY + int k; + for (k=0; klast_skip_false_probs[0][k] = cm->mbskip_pred_probs[k]; +#else + cpi->last_skip_false_probs[0] = cpi->prob_skip_false; +#endif + cpi->last_skip_probs_q[0] = cm->base_qindex; + + // update the baseline table for the current q +#if CONFIG_NEWENTROPY + for (k=0; kbase_skip_false_prob[cm->base_qindex][k] = + cm->mbskip_pred_probs[k]; +#else + cpi->base_skip_false_prob[cm->base_qindex] = cpi->prob_skip_false; +#endif + } + } + +} void vp8_initialize() { @@ -3207,13 +3260,6 @@ static void encode_frame_to_data_rate if (cpi->last_skip_false_probs[2] != 0) cpi->prob_skip_false = cpi->last_skip_false_probs[2]; #endif - - /* - if(cpi->last_skip_false_probs[2]!=0 && abs(Q- cpi->last_skip_probs_q[2])<=16 ) - cpi->prob_skip_false = cpi->last_skip_false_probs[2]; - else if (cpi->last_skip_false_probs[2]!=0) - cpi->prob_skip_false = (cpi->last_skip_false_probs[2] + cpi->prob_skip_false ) / 2; - */ } else if (cpi->common.refresh_golden_frame) { @@ -3227,13 +3273,6 @@ static void encode_frame_to_data_rate if (cpi->last_skip_false_probs[1] != 0) cpi->prob_skip_false = cpi->last_skip_false_probs[1]; #endif - - /* - if(cpi->last_skip_false_probs[1]!=0 && abs(Q- cpi->last_skip_probs_q[1])<=16 ) - cpi->prob_skip_false = cpi->last_skip_false_probs[1]; - else if (cpi->last_skip_false_probs[1]!=0) - cpi->prob_skip_false = (cpi->last_skip_false_probs[1] + cpi->prob_skip_false ) / 2; - */ } else { @@ -3248,13 +3287,6 @@ static void encode_frame_to_data_rate if (cpi->last_skip_false_probs[0] != 0) cpi->prob_skip_false = cpi->last_skip_false_probs[0]; #endif - - /* - if(cpi->last_skip_false_probs[0]!=0 && abs(Q- cpi->last_skip_probs_q[0])<=16 ) - cpi->prob_skip_false = cpi->last_skip_false_probs[0]; - else if(cpi->last_skip_false_probs[0]!=0) - cpi->prob_skip_false = (cpi->last_skip_false_probs[0] + cpi->prob_skip_false ) / 2; - */ } // as this is for cost estimate, let's make sure it does not @@ -3298,6 +3330,10 @@ static void encode_frame_to_data_rate // transform / motion compensation build reconstruction frame vp8_encode_frame(cpi); + // Update the skip mb flag probabilities based on the distribution + // seen in the last encoder iteration. + update_base_skip_probs( cpi ); + cpi->projected_frame_size -= vp8_estimate_entropy_savings(cpi); cpi->projected_frame_size = (cpi->projected_frame_size > 0) ? cpi->projected_frame_size : 0; @@ -3706,6 +3742,10 @@ static void encode_frame_to_data_rate cpi->twopass.gf_group_bits = 0 ; } + // Update the skip mb flag probabilities based on the distribution seen + // in this frame. + update_base_skip_probs( cpi ); +/* if (cm->frame_type != KEY_FRAME) { if (cpi->common.refresh_alt_ref_frame) @@ -3751,7 +3791,7 @@ static void encode_frame_to_data_rate } } - +*/ #if 0 && CONFIG_INTERNAL_STATS { FILE *f = fopen("tmp.stt", "a"); diff --git a/vp8/encoder/rdopt.c b/vp8/encoder/rdopt.c index 2582c64..19d0c60 100644 --- a/vp8/encoder/rdopt.c +++ b/vp8/encoder/rdopt.c @@ -1514,13 +1514,26 @@ int vp8_cost_mv_ref(VP8_COMP *cpi, MB_PREDICTION_MODE m, const int near_mv_ref_ct[4]) { - VP8_COMMON *pc = &cpi->common; + MACROBLOCKD *xd = &cpi->mb.e_mbd; + int segment_id = xd->mode_info_context->mbmi.segment_id; + + // If the mode coding is done entirely at the segment level + // we should not account for it at the per mb level in rd code. + // Note that if the segment level coding is expanded from single mode + // to multiple mode masks as per reference frame coding we will need + // to do something different here. + if ( !segfeature_active( xd, segment_id, SEG_LVL_MODE) ) + { + VP8_COMMON *pc = &cpi->common; - vp8_prob p [VP8_MVREFS-1]; - assert(NEARESTMV <= m && m <= SPLITMV); - vp8_mv_ref_probs(pc, p, near_mv_ref_ct); - return vp8_cost_token(vp8_mv_ref_tree, p, - vp8_mv_ref_encoding_array - NEARESTMV + m); + vp8_prob p [VP8_MVREFS-1]; + assert(NEARESTMV <= m && m <= SPLITMV); + vp8_mv_ref_probs(pc, p, near_mv_ref_ct); + return vp8_cost_token(vp8_mv_ref_tree, p, + vp8_mv_ref_encoding_array - NEARESTMV + m); + } + else + return 0; } void vp8_set_mbmode_and_mvs(MACROBLOCK *x, MB_PREDICTION_MODE mb, int_mv *mv) @@ -3241,21 +3254,6 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int vp8_cost_bit( get_pred_prob( cm, xd, PRED_COMP ), 1 ); } - // Where skip is allowable add in the default per mb cost for the no skip case. - // where we then decide to skip we have to delete this and replace it with the - // cost of signaling a skip - if (cpi->common.mb_no_coeff_skip) - { -#if CONFIG_NEWENTROPY - int prob_skip_cost = vp8_cost_bit( - get_pred_prob(cm, &x->e_mbd, PRED_MBSKIP), 0); -#else - int prob_skip_cost = vp8_cost_bit(cpi->prob_skip_false, 0); -#endif - other_cost += prob_skip_cost; - rate2 += prob_skip_cost; - } - if (cpi->common.comp_pred_mode == HYBRID_PREDICTION) { rate2 += compmode_cost; @@ -3268,13 +3266,18 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int if (!disable_skip) { - // Test for the condition where skip block will be activated because there are no non zero coefficients and make any necessary adjustment for rate - if (cpi->common.mb_no_coeff_skip) + // Test for the condition where skip block will be activated + // because there are no non zero coefficients and make any + // necessary adjustment for rate. Ignore if skip is coded at + // segment level as the cost wont have been added in. + if ( cpi->common.mb_no_coeff_skip ) { int mb_skippable; + int mb_skip_allowed; int has_y2 = ( this_mode!=SPLITMV &&this_mode!=B_PRED &&this_mode!=I8X8_PRED); + if((cpi->common.txfm_mode == ALLOW_8X8) && has_y2) { if(x->e_mbd.mode_info_context->mbmi.ref_frame!=INTRA_FRAME) @@ -3292,37 +3295,59 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int & mby_is_skippable(&x->e_mbd, has_y2); } + // Is Mb level skip allowed for this mb. + mb_skip_allowed = + !segfeature_active( xd, segment_id, SEG_LVL_EOB ) || + get_segdata( xd, segment_id, SEG_LVL_EOB ); + if (mb_skippable) { -#if CONFIG_NEWENTROPY - vp8_prob skip_prob = get_pred_prob(cm, &x->e_mbd, PRED_MBSKIP); -#endif - int prob_skip_cost; + // Back out the coefficient coding costs rate2 -= (rate_y + rate_uv); //for best_yrd calculation rate_uv = 0; -#if CONFIG_NEWENTROPY - if (skip_prob) + if ( mb_skip_allowed ) { - prob_skip_cost = vp8_cost_bit(skip_prob, 1); - prob_skip_cost -= vp8_cost_bit(skip_prob, 0); - rate2 += prob_skip_cost; - other_cost += prob_skip_cost; - } + int prob_skip_cost; + + // Cost the skip mb case +#if CONFIG_NEWENTROPY + vp8_prob skip_prob = + get_pred_prob(cm, &x->e_mbd, PRED_MBSKIP); + + if (skip_prob) + { + prob_skip_cost = vp8_cost_bit(skip_prob, 1); + rate2 += prob_skip_cost; + other_cost += prob_skip_cost; + } #else - // Back out no skip flag costing and add in skip flag costing - if (cpi->prob_skip_false) - { - prob_skip_cost = vp8_cost_bit(cpi->prob_skip_false, 1); - prob_skip_cost -= vp8_cost_bit(cpi->prob_skip_false, 0); - rate2 += prob_skip_cost; - other_cost += prob_skip_cost; - } + if (cpi->prob_skip_false) + { + prob_skip_cost = + vp8_cost_bit(cpi->prob_skip_false, 1); + rate2 += prob_skip_cost; + other_cost += prob_skip_cost; + } #endif + } + } + // Add in the cost of the no skip flag. + else if ( mb_skip_allowed ) + { + #if CONFIG_NEWENTROPY + int prob_skip_cost = vp8_cost_bit( + get_pred_prob(cm, &x->e_mbd, PRED_MBSKIP), 0); + #else + int prob_skip_cost = vp8_cost_bit(cpi->prob_skip_false, 0); + #endif + rate2 += prob_skip_cost; + other_cost += prob_skip_cost; } } - // Calculate the final RD estimate for this mode + + // Calculate the final RD estimate for this mode. this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2); } -- 2.7.4