diff --git a/vp8/decoder/decodemv.c b/vp8/decoder/decodemv.c index bee47ef3e17229020a716e7d0b5fe46a0dd1afad..c5e75d26d87dbb19ea0aff79a04ca3bd990bbd3f 100644 --- a/vp8/decoder/decodemv.c +++ b/vp8/decoder/decodemv.c @@ -248,6 +248,65 @@ static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi, // Segment reference frame features not available if ( !seg_ref_active ) { +#if CONFIG_COMPRED + // Values used in prediction model coding + unsigned char prediction_flag; + vp8_prob pred_prob; + MV_REFERENCE_FRAME pred_ref; + + // Get the context probability the prediction flag + pred_prob = get_pred_prob( cm, xd, PRED_REF ); + + // Read the prediction status flag + prediction_flag = (unsigned char)vp8_read( bc, pred_prob ); + + // Store the prediction flag. + set_pred_flag( xd, PRED_REF, prediction_flag ); + + // Get the predicted reference frame. + pred_ref = get_pred_ref( cm, xd ); + + // If correctly predicted then use the predicted value + if ( prediction_flag ) + { + ref_frame = pred_ref; + } + // else decode the explicitly coded value + else + { + vp8_prob * mod_refprobs = cm->mod_refprobs[pred_ref]; + + // Default to INTRA_FRAME (value 0) + ref_frame = INTRA_FRAME; + + // Do we need to decode the Intra/Inter branch + if ( mod_refprobs[0] ) + ref_frame = (MV_REFERENCE_FRAME) vp8_read(bc, mod_refprobs[0]); + else + ref_frame ++; + + if (ref_frame) + { + // Do we need to decode the Last/Gf_Arf branch + if ( mod_refprobs[1] ) + ref_frame += vp8_read(bc, mod_refprobs[1]); + else + ref_frame++; + + if ( ref_frame > 1 ) + { + // Do we need to decode the GF/Arf branch + if ( mod_refprobs[2] ) + ref_frame += vp8_read(bc, mod_refprobs[2]); + else + { + ref_frame = (pred_ref == GOLDEN_FRAME) + ? ALTREF_FRAME : GOLDEN_FRAME; + } + } + } + } +#else ref_frame = (MV_REFERENCE_FRAME) vp8_read(bc, cm->prob_intra_coded); @@ -259,12 +318,20 @@ static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi, (int)(1 + vp8_read(bc, cm->prob_gf_coded))); } } +#endif } //#if CONFIG_SEGFEATURES // Segment reference frame features are enabled else { +#if CONFIG_COMPRED + // The reference frame for the mb is considered as correclty predicted + // if it is signaled at the segment level for the purposes of the + // common prediction model + set_pred_flag( xd, PRED_REF, 1 ); +#endif + // If there are no inter reference frames enabled we can set INTRA if ( !check_segref_inter(xd, segment_id) ) { @@ -397,6 +464,11 @@ static void mb_mode_mv_init(VP8D_COMP *pbi) cm->prob_last_coded = (vp8_prob)vp8_read_literal(bc, 8); cm->prob_gf_coded = (vp8_prob)vp8_read_literal(bc, 8); +#if CONFIG_COMPRED + // Computes a modified set of probabilities for use when reference + // frame prediction fails. + compute_mod_refprobs( cm ); +#endif #if CONFIG_DUALPRED pbi->common.dual_pred_mode = vp8_read(bc, 128); diff --git a/vp8/decoder/decodframe.c b/vp8/decoder/decodframe.c index bb15f69566f3a713c11465fcc49379f418af36f4..5f0266b4458fe2f5d430579c7065551f51d44065 100644 --- a/vp8/decoder/decodframe.c +++ b/vp8/decoder/decodframe.c @@ -1146,6 +1146,26 @@ int vp8_decode_frame(VP8D_COMP *pbi) } } +#if CONFIG_COMPRED + // Read common prediction model status flag probability updates for the + // reference frame + if ( pc->frame_type == KEY_FRAME ) + { + // Set the prediction probabilities to defaults + pc->ref_pred_probs[0] = 120; + pc->ref_pred_probs[1] = 80; + pc->ref_pred_probs[2] = 40; + } + else + { + for (i = 0; i < PREDICTION_PROBS; i++) + { + if ( vp8_read_bit(bc) ) + pc->ref_pred_probs[i] = (vp8_prob)vp8_read_literal(bc, 8); + } + } +#endif + /* Read the loop filter level and type */ pc->filter_type = (LOOPFILTERTYPE) vp8_read_bit(bc); pc->filter_level = vp8_read_literal(bc, 6); diff --git a/vp8/encoder/bitstream.c b/vp8/encoder/bitstream.c index 37292fa7184c6af98ceb8c8c49ddd7cc4b7dcf13..346543ab35f2619e62eea994377cfe055ba36b07 100644 --- a/vp8/encoder/bitstream.c +++ b/vp8/encoder/bitstream.c @@ -851,6 +851,49 @@ static void encode_ref_frame( vp8_writer *const w, // If segment level coding of this signal is disabled... if ( !seg_ref_active ) { +#if CONFIG_COMPRED + // Values used in prediction model coding + unsigned char prediction_flag; + vp8_prob pred_prob; + + // Get the context probability the prediction flag + pred_prob = get_pred_prob( cm, xd, PRED_REF ); + + // Code the prediction flag + prediction_flag = get_pred_flag( xd, PRED_REF ); + vp8_write( w, prediction_flag, pred_prob ); + + // If not predicted correctly then code value explicitly + if ( !prediction_flag ) + { + // Get the predicted value so that it can be excluded. + MV_REFERENCE_FRAME pred_rf = get_pred_ref( cm, xd ); + + vp8_prob * mod_refprobs = cm->mod_refprobs[pred_rf]; + + if ( mod_refprobs[0] ) + { + vp8_write(w, (rf != INTRA_FRAME), mod_refprobs[0] ); + } + + // Inter coded + if (rf != INTRA_FRAME) + { + if ( mod_refprobs[1] ) + { + vp8_write(w, (rf != LAST_FRAME), mod_refprobs[1] ); + } + + if (rf != LAST_FRAME) + { + if ( mod_refprobs[2] ) + { + vp8_write(w, (rf != GOLDEN_FRAME), mod_refprobs[2] ); + } + } + } + } +#else if (rf == INTRA_FRAME) { vp8_write(w, 0, cm->prob_intra_coded); @@ -870,6 +913,7 @@ static void encode_ref_frame( vp8_writer *const w, vp8_write(w, (rf == GOLDEN_FRAME) ? 0 : 1, cm->prob_gf_coded); } } +#endif } //#if CONFIG_SEGFEATURES // Else use the segment @@ -971,6 +1015,11 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) if (!pc->prob_gf_coded) pc->prob_gf_coded = 1; +#if CONFIG_COMPRED + // Compute a modified set of probabilities to use when prediction of the + // reference frame fails + compute_mod_refprobs( pc ); +#endif #ifdef ENTROPY_STATS active_section = 1; @@ -1598,6 +1647,9 @@ static int default_coef_context_savings(VP8_COMP *cpi) return savings; } +#if CONFIG_COMPRED +// TODO... this will all need changing for new reference frame coding model +#endif int vp8_estimate_entropy_savings(VP8_COMP *cpi) { int savings = 0; @@ -2179,6 +2231,24 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size) } } +#if CONFIG_COMPRED + // Encode the common prediction model status flag probability updates for + // the reference frame + if ( pc->frame_type != KEY_FRAME ) + { + for (i = 0; i < PREDICTION_PROBS; i++) + { + if ( cpi->ref_probs_update[i] ) + { + vp8_write_bit(bc, 1); + vp8_write_literal(bc, pc->ref_pred_probs[i], 8); + } + else + vp8_write_bit(bc, 0); + } + } +#endif + // Encode the loop filter level and type vp8_write_bit(bc, pc->filter_type); vp8_write_literal(bc, pc->filter_level, 6); diff --git a/vp8/encoder/encodeframe.c b/vp8/encoder/encodeframe.c index a9af839310df5fa5a25459d9feb79721d8d92c1b..c221b2f6f6894168a8fb7757e2273fd1ac68d8b7 100644 --- a/vp8/encoder/encodeframe.c +++ b/vp8/encoder/encodeframe.c @@ -31,6 +31,7 @@ #include <limits.h> #include "vp8/common/subpixel.h" #include "vpx_ports/vpx_timer.h" +#include "vp8/common/pred_common.h" //#if CONFIG_SEGFEATURES //#define DBG_PRNT_SEGMAP 1 @@ -880,6 +881,13 @@ void init_encode_frame_mb_context(VP8_COMP *cpi) vpx_memset(cm->above_context, 0, sizeof(ENTROPY_CONTEXT_PLANES) * cm->mb_cols); + +//#if CONFIG_COMPRED +// TODO... this will all need changing for new reference frame coding model +// in addition... ref_frame_cost should not be in the MACROBLOCKD structure as +// it is only referenced in the encoder. +//#endif + xd->ref_frame_cost[INTRA_FRAME] = vp8_cost_zero(cm->prob_intra_coded); // Special case treatment when GF and ARF are not sensible options for reference @@ -921,6 +929,12 @@ static void encode_frame_internal(VP8_COMP *cpi) TOKENEXTRA *tp = cpi->tok; int totalrate; +#if CONFIG_COMPRED + // Compute a modified set of reference frame probabilities to use when + // prediction fails. These are based on the current genreal estimates for + // this frame which may be updated with each itteration of the recode loop. + compute_mod_refprobs( cm ); +#endif //#if CONFIG_SEGFEATURES // debug output @@ -1529,11 +1543,16 @@ int vp8cx_encode_inter_macroblock int recon_yoffset, int recon_uvoffset ) { + VP8_COMMON *cm = &cpi->common; MACROBLOCKD *const xd = &x->e_mbd; int intra_error = 0; int rate; int distortion; unsigned char *segment_id = &xd->mode_info_context->mbmi.segment_id; + int seg_ref_active; +#if CONFIG_COMPRED + unsigned char ref_pred_flag; +#endif x->skip = 0; @@ -1677,18 +1696,42 @@ int vp8cx_encode_inter_macroblock } //#if CONFIG_SEGFEATURES + seg_ref_active = segfeature_active( xd, *segment_id, SEG_LVL_REF_FRAME ); + +#if CONFIG_COMPRED + // SET VARIOUS PREDICTION FLAGS + + // Did the chosen reference frame match its predicted value. + // If the reference frame is predicted at the segment level we + // mark it as correctly predicted + ref_pred_flag = ( (xd->mode_info_context->mbmi.ref_frame == + get_pred_ref( cm, xd )) || + seg_ref_active ); + set_pred_flag( xd, PRED_REF, ref_pred_flag ); +#endif + // If we have just a single reference frame coded for a segment then // exclude from the reference frame counts used to work out // probabilities. NOTE: At the moment we dont support custom trees // for the reference frame coding for each segment but this is a // possible future action. - if ( !segfeature_active( xd, *segment_id, SEG_LVL_REF_FRAME ) || + if ( !seg_ref_active || ( ( check_segref( xd, *segment_id, INTRA_FRAME ) + check_segref( xd, *segment_id, LAST_FRAME ) + check_segref( xd, *segment_id, GOLDEN_FRAME ) + check_segref( xd, *segment_id, ALTREF_FRAME ) ) > 1 ) ) { - cpi->count_mb_ref_frame_usage[xd->mode_info_context->mbmi.ref_frame]++; +// TODO this may not be a good idea as it makes sample size small and means +// the predictor functions cannot use data about most likely value only most +// likely unpredicted value. +//#if CONFIG_COMPRED +// // Only update count for incorrectly predicted cases +// if ( !ref_pred_flag ) +//#endif + { + cpi->count_mb_ref_frame_usage + [xd->mode_info_context->mbmi.ref_frame]++; + } } if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index 675546dc4522e1141fad0589b06de621be4e01ba..7299086291b2c8845095eea184d329bebdf75655 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -37,6 +37,7 @@ //#if CONFIG_SEGFEATURES #include "vp8/common/seg_common.h" #include "mbgraph.h" +#include "vp8/common/pred_common.h" #if ARCH_ARM #include "vpx_ports/arm.h" @@ -268,7 +269,6 @@ void vp8_initialize() { static int init_done = 0; - if (!init_done) { vp8_scale_machine_specific_config(); @@ -574,7 +574,14 @@ static void init_seg_features(VP8_COMP *cpi) set_segdata( xd, 1, SEG_LVL_ALT_LF, -2 ); enable_segfeature(xd, 1, SEG_LVL_ALT_LF); +#if CONFIG_COMPRED + // Segment coding disabled for compred testing + if ( high_q || (cpi->static_mb_pct == 100) ) + //if ( 0 ) +#else if ( high_q || (cpi->static_mb_pct == 100) ) + //if ( 0 ) +#endif { set_segref(xd, 1, ALTREF_FRAME); enable_segfeature(xd, 1, SEG_LVL_REF_FRAME); @@ -610,11 +617,20 @@ static void init_seg_features(VP8_COMP *cpi) // Special case where we are coding over the top of a previous // alt ref frame +#if CONFIG_COMPRED + // Segment coding disabled for compred testing else if ( cpi->is_src_frame_alt_ref ) + //else if ( 0 ) +#else + else if ( cpi->is_src_frame_alt_ref ) + //else if ( 0 ) +#endif { // Enable mode and ref frame features for segment 0 as well enable_segfeature(xd, 0, SEG_LVL_REF_FRAME); enable_segfeature(xd, 0, SEG_LVL_MODE); + enable_segfeature(xd, 1, SEG_LVL_REF_FRAME); + enable_segfeature(xd, 1, SEG_LVL_MODE); // All mbs should use ALTREF_FRAME, ZEROMV exclusively clear_segref(xd, 0); @@ -2379,7 +2395,7 @@ VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf) // Create the encoder segmentation map and set all entries to 0 CHECK_MEM_ERROR(cpi->segmentation_map, vpx_calloc((cpi->common.mb_rows * cpi->common.mb_cols), 1)); - // And a copy "last_segmentation_map" for temporal coding + // And a copy in common for temporal coding CHECK_MEM_ERROR(cm->last_frame_seg_map, vpx_calloc((cpi->common.mb_rows * cpi->common.mb_cols), 1)); @@ -3411,6 +3427,7 @@ static void update_golden_frame_stats(VP8_COMP *cpi) } } +#if !CONFIG_COMPRED // This function updates the reference frame probability estimates that // will be used during mode selection static void update_rd_ref_frame_probs(VP8_COMP *cpi) @@ -3525,7 +3542,7 @@ static void update_rd_ref_frame_probs(VP8_COMP *cpi) #endif } - +#endif // 1 = key, 0 = inter static int decide_key_frame(VP8_COMP *cpi) @@ -3865,6 +3882,133 @@ void loopfilter_frame(VP8_COMP *cpi, VP8_COMMON *cm) } +#if CONFIG_COMPRED +// This function updates the reference frame prediction stats +static void update_refpred_stats( VP8_COMP *cpi ) +{ + VP8_COMMON *const cm = & cpi->common; + MACROBLOCKD *const xd = & cpi->mb.e_mbd; + + int mb_row, mb_col; + int i; + int tot_count; + int ref_pred_count[PREDICTION_PROBS][2]; + vp8_prob new_pred_probs[PREDICTION_PROBS]; + unsigned char pred_context; + unsigned char pred_flag; + + int old_cost, new_cost; + + // Clear the prediction hit counters + vpx_memset(ref_pred_count, 0, sizeof(ref_pred_count)); + + // Set the prediction probability structures to defaults + if ( cm->frame_type == KEY_FRAME ) + { + // Set the prediction probabilities to defaults + cm->ref_pred_probs[0] = 120; + cm->ref_pred_probs[1] = 80; + cm->ref_pred_probs[2] = 40; + vpx_memset(cpi->ref_probs_update, 0, sizeof(cpi->ref_probs_update) ); + } + else + { + // For non-key frames....... + + // Scan through the macroblocks and collate prediction counts. + xd->mode_info_context = cm->mi; + for (mb_row = 0; mb_row < cm->mb_rows; mb_row++) + { + for (mb_col = 0; mb_col < cm->mb_cols; mb_col++) + { + // Get the prediction context and status + pred_flag = get_pred_flag( xd, PRED_REF ); + pred_context = get_pred_context( cm, xd, PRED_REF ); + + // Count prediction success + ref_pred_count[pred_context][pred_flag]++; + + // Step on to the next mb + xd->mode_info_context++; + } + + // this is to account for the border in mode_info_context + xd->mode_info_context++; + } + + // TEMP / Print out prediction quality numbers + if (0) + { + FILE *f = fopen("predquality.stt", "a"); + int pred0, pred1, pred2; + + + pred0 = ref_pred_count[0][0] + ref_pred_count[0][1]; + if ( pred0 ) + pred0 = (ref_pred_count[0][1] * 255) / pred0; + + pred1 = ref_pred_count[1][0] + ref_pred_count[1][1]; + if ( pred1 ) + pred1 = (ref_pred_count[1][1] * 255) / pred1; + + pred2 = ref_pred_count[2][0] + ref_pred_count[2][1]; + if ( pred2 ) + pred2 = (ref_pred_count[2][1] * 255) / pred2; + + fprintf(f, "%8d: %8d %8d: %8d %8d: %8d %8d\n", + cm->current_video_frame, + pred0, ref_pred_count[0][1], + pred1, ref_pred_count[1][1], + pred2, ref_pred_count[2][1] ); + fclose(f); + } + + // From the prediction counts set the probabilities for each context + for ( i = 0; i < PREDICTION_PROBS; i++ ) + { + // MB reference frame not relevent to key frame encoding + if ( cm->frame_type != KEY_FRAME ) + { + // Work out the probabilities for the reference frame predictor + tot_count = ref_pred_count[i][0] + ref_pred_count[i][1]; + if ( tot_count ) + { + new_pred_probs[i] = + ( ref_pred_count[i][0] * 255 ) / tot_count; + + // Clamp to minimum allowed value + new_pred_probs[i] += !new_pred_probs[i]; + } + else + new_pred_probs[i] = 128; + } + else + new_pred_probs[i] = 128; + + // Decide whether or not to update the reference frame probs. + // Returned costs are in 1/256 bit units. + old_cost = + (ref_pred_count[i][0] * vp8_cost_zero(cm->ref_pred_probs[i])) + + (ref_pred_count[i][1] * vp8_cost_one(cm->ref_pred_probs[i])); + + new_cost = + (ref_pred_count[i][0] * vp8_cost_zero(new_pred_probs[i])) + + (ref_pred_count[i][1] * vp8_cost_one(new_pred_probs[i])); + + // Cost saving must be >= 8 bits (2048 in these units) + if ( (old_cost - new_cost) >= 2048 ) + { + cpi->ref_probs_update[i] = 1; + cm->ref_pred_probs[i] = new_pred_probs[i]; + } + else + cpi->ref_probs_update[i] = 0; + + } + } +} +#endif + static void encode_frame_to_data_rate ( VP8_COMP *cpi, @@ -4021,7 +4165,9 @@ static void encode_frame_to_data_rate } #endif +#if !CONFIG_COMPRED update_rd_ref_frame_probs(cpi); +#endif // Test code for new segment features init_seg_features( cpi ); @@ -4872,6 +5018,12 @@ static void encode_frame_to_data_rate cpi->segmentation_map, cm->MBs ); } +#if CONFIG_COMPRED + // Update the common prediction model probabilities to reflect + // the what was seen in the current frame. + update_refpred_stats( cpi ); +#endif + // build the bitstream vp8_pack_bitstream(cpi, dest, size); diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h index 5cb8834e3d45888428ae322eede23c85c9a4ff8d..214006cfd6a74d52a53557995ec6e4e0a1797917 100644 --- a/vp8/encoder/onyx_int.h +++ b/vp8/encoder/onyx_int.h @@ -512,14 +512,15 @@ typedef struct VP8_COMP #if CONFIG_DUALPRED int prob_dualpred[3]; #endif /* CONFIG_DUALPRED */ - int recent_ref_frame_usage[MAX_REF_FRAMES]; + int recent_ref_frame_usage[MAX_REF_FRAMES]; int count_mb_ref_frame_usage[MAX_REF_FRAMES]; int this_frame_percent_intra; int last_frame_percent_intra; - int ref_frame_flags; + unsigned char ref_probs_update[PREDICTION_PROBS]; + SPEED_FEATURES sf; int error_bins[1024]; diff --git a/vp8/encoder/pickinter.c b/vp8/encoder/pickinter.c index 19ab4d434ec63de7a398549c2495bcc983ba4f4b..5de312d82452c8901bef99701c9d2fa9af856c6b 100644 --- a/vp8/encoder/pickinter.c +++ b/vp8/encoder/pickinter.c @@ -597,6 +597,10 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, x->e_mbd.mode_info_context->mbmi.mode = this_mode; x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED; + +// #if CONFIG_COMPRED +// TODO... this will all need changing for new reference frame coding model +// #endif // Work out the cost assosciated with selecting the reference frame frame_cost = x->e_mbd.ref_frame_cost[x->e_mbd.mode_info_context->mbmi.ref_frame]; diff --git a/vp8/encoder/rdopt.c b/vp8/encoder/rdopt.c index 45db403f60a2b2686d3eead0c231fe7099a9f063..e5f1146edfc0ded87ec94949946103af59025f8c 100644 --- a/vp8/encoder/rdopt.c +++ b/vp8/encoder/rdopt.c @@ -40,6 +40,7 @@ //#if CONFIG_SEGFEATURES #include "vp8/common/seg_common.h" +#include "vp8/common/pred_common.h" #if CONFIG_RUNTIME_CPU_DETECT #define IF_RTCD(x) (x) @@ -47,7 +48,6 @@ #define IF_RTCD(x) NULL #endif - extern void vp8cx_mb_init_quantizer(VP8_COMP *cpi, MACROBLOCK *x); extern void vp8_update_zbin_extra(VP8_COMP *cpi, MACROBLOCK *x); @@ -2030,6 +2030,66 @@ static void set_i8x8_block_modes(MACROBLOCK *x, int *modes) } } +#if CONFIG_COMPRED +void vp8_estimate_ref_frame_costs(VP8_COMP *cpi, unsigned int * ref_costs ) +{ + VP8_COMMON *cm = &cpi->common; + MACROBLOCKD *xd = &cpi->mb.e_mbd; + vp8_prob * mod_refprobs; + + unsigned int cost; + int pred_ref ; + int pred_flag; + int i; + + vp8_prob pred_prob; + + // Get the predicted reference for this mb + pred_ref = get_pred_ref( cm, xd ); + + // Get the context probability for the prediction flag + pred_prob = get_pred_prob( cm, xd, PRED_REF ); + + // Get the set of probailities to use if prediction fails + mod_refprobs = cm->mod_refprobs[pred_ref]; + + // For each possible selected reference frame work out a cost. + // TODO: correct handling of costs if segment indicates only a subset of + // reference frames are allowed... though mostly this should come out + // in the wash. + for ( i = 0; i < MAX_REF_FRAMES; i++ ) + { + pred_flag = (i == pred_ref); + + // Get the prediction for the current mb + cost = vp8_cost_bit( pred_prob, pred_flag ); + + // for incorectly predicted cases + if ( ! pred_flag ) + { + if ( mod_refprobs[0] ) + cost += vp8_cost_bit( (i != INTRA_FRAME), mod_refprobs[0] ); + + // Inter coded + if (i != INTRA_FRAME) + { + if ( mod_refprobs[1] ) + cost += vp8_cost_bit( (i != LAST_FRAME), mod_refprobs[1] ); + + if (i != LAST_FRAME) + { + if ( mod_refprobs[2] ) + cost += vp8_cost_bit( (i != GOLDEN_FRAME), + mod_refprobs[2] ); + } + } + } + + ref_costs[i] = cost; + } +} +#endif + void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int recon_uvoffset, int *returnrate, int *returndistortion, int *returnintra, int *best_single_rd_diff, int *best_dual_rd_diff, @@ -2089,8 +2149,13 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int unsigned char *u_buffer[4]; unsigned char *v_buffer[4]; +#if CONFIG_COMPRED + unsigned int ref_costs[MAX_REF_FRAMES]; +#endif + vpx_memset(&best_mbmode, 0, sizeof(best_mbmode)); vpx_memset(&best_bmodes, 0, sizeof(best_bmodes)); + #if CONFIG_DUALPRED for (i = 0; i < 4; i++) { @@ -2158,6 +2223,12 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int rd_pick_intra_mbuv_mode(cpi, x, &uv_intra_rate, &uv_intra_rate_tokenonly, &uv_intra_distortion); uv_intra_mode = x->e_mbd.mode_info_context->mbmi.uv_mode; +#if CONFIG_COMPRED + // Get estimates of reference frame costs for each reference frame + // that depend on the current prediction etc. + vp8_estimate_ref_frame_costs( cpi, ref_costs ); +#endif + for (mode_index = 0; mode_index < MAX_MODES; mode_index++) { int this_rd = INT_MAX; @@ -2733,11 +2804,15 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int } #endif /* CONFIG_DUALPRED */ - /* Estimate the reference frame signaling cost and add it - * to the rolling cost variable. - */ + + // Estimate the reference frame signaling cost and add it + // to the rolling cost variable. +#if CONFIG_COMPRED + rate2 += ref_costs[x->e_mbd.mode_info_context->mbmi.ref_frame]; +#else rate2 += x->e_mbd.ref_frame_cost[x->e_mbd.mode_info_context->mbmi.ref_frame]; +#endif if (!disable_skip) { @@ -2818,8 +2893,12 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int x->e_mbd.mode_info_context->mbmi.mv.as_int = 0; } +#if CONFIG_COMPRED + other_cost += ref_costs[x->e_mbd.mode_info_context->mbmi.ref_frame]; +#else other_cost += - x->e_mbd.ref_frame_cost[x->e_mbd.mode_info_context->mbmi.ref_frame]; + x->e_mbd.ref_frame_cost[x->e_mbd.mode_info_context->mbmi.ref_frame]; +#endif /* Calculate the final y RD estimate for this mode */ best_yrd = RDCOST(x->rdmult, x->rddiv, (rate2-rate_uv-other_cost),