diff --git a/vp8/common/onyxc_int.h b/vp8/common/onyxc_int.h index fd6a55801..a86635a7c 100644 --- a/vp8/common/onyxc_int.h +++ b/vp8/common/onyxc_int.h @@ -236,6 +236,7 @@ typedef struct VP8Common #if CONFIG_COMPRED // Context probabilities for reference frame prediction + unsigned char ref_scores[MAX_REF_FRAMES]; vp8_prob ref_pred_probs[PREDICTION_PROBS]; vp8_prob mod_refprobs[MAX_REF_FRAMES][PREDICTION_PROBS]; #endif diff --git a/vp8/common/pred_common.c b/vp8/common/pred_common.c index e4cd037e8..bda140058 100644 --- a/vp8/common/pred_common.c +++ b/vp8/common/pred_common.c @@ -155,10 +155,6 @@ MV_REFERENCE_FRAME get_pred_ref( VP8_COMMON *const cm, { MODE_INFO *m = xd->mode_info_context; - unsigned char left_pred; - unsigned char above_pred; - unsigned char frame_allowed[MAX_REF_FRAMES]; - MV_REFERENCE_FRAME left; MV_REFERENCE_FRAME above; MV_REFERENCE_FRAME above_left; @@ -166,106 +162,67 @@ MV_REFERENCE_FRAME get_pred_ref( VP8_COMMON *const cm, int segment_id = xd->mode_info_context->mbmi.segment_id; int seg_ref_active; + int i; + + unsigned char frame_allowed[MAX_REF_FRAMES] = {1,1,1,1}; + unsigned char ref_score[MAX_REF_FRAMES]; + unsigned char best_score = 0; + unsigned char left_in_image; + unsigned char above_in_image; + unsigned char above_left_in_image; // Is segment coding ennabled seg_ref_active = segfeature_active( xd, segment_id, SEG_LVL_REF_FRAME ); - // Reference frame used by neighbours - left = (m - 1)->mbmi.ref_frame; - above = (m - cm->mode_info_stride)->mbmi.ref_frame; - above_left = (m - 1 - cm->mode_info_stride)->mbmi.ref_frame; - - // Reference frame prediction status of immediate neigbours. - // This can only be set if the mb is "in image" - left_pred = (m - 1)->mbmi.ref_predicted; - above_pred = (m - cm->mode_info_stride)->mbmi.ref_predicted; - // Special case treatment if segment coding is enabled. // Dont allow prediction of a reference frame that the segment // does not allow if ( seg_ref_active ) { - frame_allowed[INTRA_FRAME] = - check_segref( xd, segment_id, INTRA_FRAME ); - frame_allowed[LAST_FRAME] = - check_segref( xd, segment_id, LAST_FRAME ); - frame_allowed[GOLDEN_FRAME] = - check_segref( xd, segment_id, GOLDEN_FRAME ); - frame_allowed[ALTREF_FRAME] = - check_segref( xd, segment_id, ALTREF_FRAME ); + for ( i = 0; i < MAX_REF_FRAMES; i++ ) + { + frame_allowed[i] = + check_segref( xd, segment_id, i ); + + // Score set to 0 if ref frame not allowed + ref_score[i] = cm->ref_scores[i] * frame_allowed[i]; + } } else + vpx_memcpy( ref_score, cm->ref_scores, sizeof(ref_score) ); + + // Reference frames used by neighbours + left = (m - 1)->mbmi.ref_frame; + above = (m - cm->mode_info_stride)->mbmi.ref_frame; + above_left = (m - 1 - cm->mode_info_stride)->mbmi.ref_frame; + + // Are neighbours in image + left_in_image = (m - 1)->mbmi.mb_in_image; + above_in_image = (m - cm->mode_info_stride)->mbmi.mb_in_image; + above_left_in_image = (m - 1 - cm->mode_info_stride)->mbmi.mb_in_image; + + // Adjust scores for candidate reference frames based on neigbours + if ( frame_allowed[left] && left_in_image ) { - frame_allowed[INTRA_FRAME] = 1; - frame_allowed[LAST_FRAME] = 1; - frame_allowed[GOLDEN_FRAME] = 1; - frame_allowed[ALTREF_FRAME] = 1; + ref_score[left] += 16; + if ( above_left_in_image && (left == above_left) ) + ref_score[left] += 4; + } + if ( frame_allowed[above] && above_in_image ) + { + ref_score[above] += 16; + if ( above_left_in_image && (above == above_left) ) + ref_score[above] += 4; } - // Dont predict if not allowed - left_pred = left_pred * frame_allowed[left]; - above_pred = above_pred * frame_allowed[above]; - - // Boost prediction scores of above / left if they are predicted and match - // the above left. - if ( left_pred ) - left_pred += (left == above_left); - if ( above_pred ) - above_pred += (above == above_left); - - // Only consider "in image" mbs as giving valid prediction. - if ( (left == above) && frame_allowed[left] && - ((m - 1)->mbmi.mb_in_image || - (m - cm->mode_info_stride)->mbmi.mb_in_image) ) + // Now choose the candidate with the highest score + for ( i = 0; i < MAX_REF_FRAMES; i++ ) { - pred_ref = left; - } - else if ( left_pred > above_pred ) - { - pred_ref = left; - } - else if ( above_pred > left_pred ) - { - pred_ref = above; - } - // If we reach this clause left_pred and above_pred must be the same - else if ( left_pred > 0 ) - { - // Choose from above or left. - // For now this is based on a fixed preference order. - // Last,Altref,Golden - if ( frame_allowed[LAST_FRAME] && - ((left == LAST_FRAME) || (above == LAST_FRAME)) ) + if ( ref_score[i] > best_score ) { - pred_ref = LAST_FRAME; + pred_ref = i; + best_score = ref_score[i]; } - else if ( frame_allowed[ALTREF_FRAME] && - ((left == ALTREF_FRAME) || (above == ALTREF_FRAME)) ) - { - pred_ref = ALTREF_FRAME; - } - else if ( frame_allowed[GOLDEN_FRAME] && - ((left == GOLDEN_FRAME) || (above == GOLDEN_FRAME)) ) - { - pred_ref = GOLDEN_FRAME; - } - else - { - pred_ref = INTRA_FRAME; - } - } - // No prediction case.. choose in fixed order from allowed options - // TBD could order based onf frequency. - else - { - if ( frame_allowed[LAST_FRAME] ) - pred_ref = LAST_FRAME; - else if ( frame_allowed[ALTREF_FRAME] ) - pred_ref = ALTREF_FRAME; - else if ( frame_allowed[GOLDEN_FRAME] ) - pred_ref = GOLDEN_FRAME; - else - pred_ref = INTRA_FRAME; } return pred_ref; @@ -357,5 +314,13 @@ void compute_mod_refprobs( VP8_COMMON *const cm ) norm_cnt[3] = 0; calc_ref_probs( norm_cnt, cm->mod_refprobs[ALTREF_FRAME] ); cm->mod_refprobs[ALTREF_FRAME][2] = 0; // This branch implicit + + // Score the reference frames based on overal frequency. + // These scores contribute to the prediction choices. + // Max score 17 min 1 + cm->ref_scores[INTRA_FRAME] = 1 + (intra_count * 16 / 255); + cm->ref_scores[LAST_FRAME] = 1 + (last_count * 16 / 255); + cm->ref_scores[GOLDEN_FRAME] = 1 + (gf_count * 16 / 255); + cm->ref_scores[ALTREF_FRAME] = 1 + (arf_count * 16 / 255); } #endif diff --git a/vp8/decoder/decodemv.c b/vp8/decoder/decodemv.c index 432b339b1..4238e4d18 100644 --- a/vp8/decoder/decodemv.c +++ b/vp8/decoder/decodemv.c @@ -292,7 +292,6 @@ static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi, // else decode the explicitly coded value else { - //vp8_prob * mod_refprobs = cm->mod_refprobs[pred_ref]; vp8_prob mod_refprobs[PREDICTION_PROBS]; vpx_memcpy( mod_refprobs, cm->mod_refprobs[pred_ref], sizeof(mod_refprobs) ); diff --git a/vp8/encoder/bitstream.c b/vp8/encoder/bitstream.c index 26f1cb487..3c0ea4c2b 100644 --- a/vp8/encoder/bitstream.c +++ b/vp8/encoder/bitstream.c @@ -869,21 +869,24 @@ static void encode_ref_frame( vp8_writer *const w, // Values used in prediction model coding unsigned char prediction_flag; vp8_prob pred_prob; + MV_REFERENCE_FRAME pred_rf; // 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 ); + // Get the predicted value. + pred_rf = get_pred_ref( cm, xd ); + + // Did the chosen reference frame match its predicted value. + prediction_flag = + ( xd->mode_info_context->mbmi.ref_frame == pred_rf ); + + set_pred_flag( xd, PRED_REF, prediction_flag ); 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]; vp8_prob mod_refprobs[PREDICTION_PROBS]; vpx_memcpy( mod_refprobs, @@ -997,6 +1000,42 @@ static void encode_ref_frame( vp8_writer *const w, #endif } +// Update the probabilities used to encode reference frame data +static void update_ref_probs( VP8_COMP *const cpi ) +{ + VP8_COMMON *const cm = & cpi->common; + + const int *const rfct = cpi->count_mb_ref_frame_usage; + const int rf_intra = rfct[INTRA_FRAME]; + const int rf_inter = rfct[LAST_FRAME] + + rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]; + +//#if CONFIG_SEGFEATURES + cm->prob_intra_coded = (rf_intra + rf_inter) + ? rf_intra * 255 / (rf_intra + rf_inter) : 1; + + if (!cm->prob_intra_coded) + cm->prob_intra_coded = 1; + + cm->prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128; + + if (!cm->prob_last_coded) + cm->prob_last_coded = 1; + + cm->prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) + ? (rfct[GOLDEN_FRAME] * 255) / + (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128; + + if (!cm->prob_gf_coded) + cm->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( cm ); +#endif +} + #if CONFIG_SUPERBLOCKS static void pack_inter_mode_mvs(VP8_COMP *const cpi) { @@ -1010,9 +1049,6 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) #endif int pred_context; - const int *const rfct = cpi->count_mb_ref_frame_usage; - const int rf_intra = rfct[INTRA_FRAME]; - const int rf_inter = rfct[LAST_FRAME] + rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]; MODE_INFO *m = pc->mi; #if CONFIG_NEWNEAR MODE_INFO *prev_m = pc->prev_mi; @@ -1036,31 +1072,8 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) cpi->mb.partition_info = cpi->mb.pi; - // Calculate the probabilities to be used to code the reference frame - // based on actual useage this frame -//#if CONFIG_SEGFEATURES - pc->prob_intra_coded = (rf_intra + rf_inter) - ? rf_intra * 255 / (rf_intra + rf_inter) : 1; - - if (!pc->prob_intra_coded) - pc->prob_intra_coded = 1; - - pc->prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128; - - if (!pc->prob_last_coded) - pc->prob_last_coded = 1; - - pc->prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) - ? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128; - - 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 + // Update the probabilities used to encode reference frame data + update_ref_probs( cpi ); #ifdef ENTROPY_STATS active_section = 1; @@ -1425,9 +1438,6 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) #endif int pred_context; - const int *const rfct = cpi->count_mb_ref_frame_usage; - const int rf_intra = rfct[INTRA_FRAME]; - const int rf_inter = rfct[LAST_FRAME] + rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]; MODE_INFO *m = pc->mi; #if CONFIG_NEWNEAR @@ -1448,31 +1458,8 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) cpi->mb.partition_info = cpi->mb.pi; - // Calculate the probabilities to be used to code the reference frame - // based on actual useage this frame -//#if CONFIG_SEGFEATURES - pc->prob_intra_coded = (rf_intra + rf_inter) - ? rf_intra * 255 / (rf_intra + rf_inter) : 1; - - if (!pc->prob_intra_coded) - pc->prob_intra_coded = 1; - - pc->prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128; - - if (!pc->prob_last_coded) - pc->prob_last_coded = 1; - - pc->prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) - ? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128; - - 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 + // Update the probabilities used to encode reference frame data + update_ref_probs( cpi ); #ifdef ENTROPY_STATS active_section = 1; @@ -2825,7 +2812,7 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size) { for (i = 0; i < PREDICTION_PROBS; i++) { - if ( cpi->ref_probs_update[i] ) + if ( cpi->ref_pred_probs_update[i] ) { vp8_write_bit(bc, 1); vp8_write_literal(bc, pc->ref_pred_probs[i], 8); diff --git a/vp8/encoder/encodeframe.c b/vp8/encoder/encodeframe.c index 30352d719..2e5bd20c8 100644 --- a/vp8/encoder/encodeframe.c +++ b/vp8/encoder/encodeframe.c @@ -1982,6 +1982,7 @@ int vp8cx_encode_inter_macroblock ref_pred_flag = ( (xd->mode_info_context->mbmi.ref_frame == get_pred_ref( cm, xd )) ); set_pred_flag( xd, PRED_REF, ref_pred_flag ); + #endif // If we have just a single reference frame coded for a segment then diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index 2ea41ab35..e3656e2d8 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -3418,6 +3418,7 @@ static void update_golden_frame_stats(VP8_COMP *cpi) } #if !CONFIG_COMPRED +//#if 1 // 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) @@ -3899,7 +3900,9 @@ static void update_refpred_stats( VP8_COMP *cpi ) 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) ); + + vpx_memset(cpi->ref_pred_probs_update, 0, + sizeof(cpi->ref_pred_probs_update) ); } else { @@ -3988,11 +3991,11 @@ static void update_refpred_stats( VP8_COMP *cpi ) // Cost saving must be >= 8 bits (2048 in these units) if ( (old_cost - new_cost) >= 2048 ) { - cpi->ref_probs_update[i] = 1; + cpi->ref_pred_probs_update[i] = 1; cm->ref_pred_probs[i] = new_pred_probs[i]; } else - cpi->ref_probs_update[i] = 0; + cpi->ref_pred_probs_update[i] = 0; } } @@ -4156,6 +4159,7 @@ static void encode_frame_to_data_rate #endif #if !CONFIG_COMPRED +//#if 1 update_rd_ref_frame_probs(cpi); #endif diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h index 214006cfd..cd2f25eaa 100644 --- a/vp8/encoder/onyx_int.h +++ b/vp8/encoder/onyx_int.h @@ -519,7 +519,7 @@ typedef struct VP8_COMP int last_frame_percent_intra; int ref_frame_flags; - unsigned char ref_probs_update[PREDICTION_PROBS]; + unsigned char ref_pred_probs_update[PREDICTION_PROBS]; SPEED_FEATURES sf; int error_bins[1024];