ref: 58ec6fe8c399c3f21e8e0ba368a80270581b2aa6
parent: f0459549a60b1df09220f2abf6afefabb81b40a3
author: Paul Wilkins <paulwilkins@google.com>
date: Fri Feb 3 08:46:18 EST 2012
Modified prediction behavior for reference frame. Trial of a modified prediction function that ranks each possible reference frame based on a combination of local usage and frame level probability. The code is a bit cleaner and simpler. In direct comparison with old unpredicted method with segment level coding turned off for mode,ref & EOB the prediction gives a gain on derf of around 0.4%. There is some further gain from bug fixes over earlier code. With segment coding on the prediction method is slightly -ve on some very easy clips (at low rates) due to slightly higher overheads, but better on harder clips. Overall neutral on derf in direct comparison on latest code base, but compared to earlier code without bug fixes about +0.7% overall psnr +0.3% SSIM. Change-Id: I5b8474658b208134d352d24f6517f25795490789
--- a/vp8/common/onyxc_int.h
+++ b/vp8/common/onyxc_int.h
@@ -236,6 +236,7 @@
#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
--- a/vp8/common/pred_common.c
+++ b/vp8/common/pred_common.c
@@ -155,10 +155,6 @@
{
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,107 +162,68 @@
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
- {
- frame_allowed[INTRA_FRAME] = 1;
- frame_allowed[LAST_FRAME] = 1;
- frame_allowed[GOLDEN_FRAME] = 1;
- frame_allowed[ALTREF_FRAME] = 1;
- }
+ vpx_memcpy( ref_score, cm->ref_scores, sizeof(ref_score) );
- // Dont predict if not allowed
- left_pred = left_pred * frame_allowed[left];
- above_pred = above_pred * frame_allowed[above];
+ // 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;
- // 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);
+ // 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;
- // 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) )
+ // Adjust scores for candidate reference frames based on neigbours
+ if ( frame_allowed[left] && left_in_image )
{
- pred_ref = left;
+ ref_score[left] += 16;
+ if ( above_left_in_image && (left == above_left) )
+ ref_score[left] += 4;
}
- else if ( left_pred > above_pred )
+ if ( frame_allowed[above] && above_in_image )
{
- pred_ref = left;
+ ref_score[above] += 16;
+ if ( above_left_in_image && (above == above_left) )
+ ref_score[above] += 4;
}
- else if ( above_pred > left_pred )
+
+ // Now choose the candidate with the highest score
+ for ( i = 0; i < MAX_REF_FRAMES; i++ )
{
- 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 @@
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
--- a/vp8/decoder/decodemv.c
+++ b/vp8/decoder/decodemv.c
@@ -292,7 +292,6 @@
// 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) );
--- a/vp8/encoder/bitstream.c
+++ b/vp8/encoder/bitstream.c
@@ -869,21 +869,24 @@
// 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 @@
#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 @@
#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,32 +1072,9 @@
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;
+ // Update the probabilities used to encode reference frame data
+ update_ref_probs( cpi );
- 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
-
#ifdef ENTROPY_STATS
active_section = 1;
#endif
@@ -1425,9 +1438,6 @@
#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,32 +1458,9 @@
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;
+ // Update the probabilities used to encode reference frame data
+ update_ref_probs( cpi );
- 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
-
#ifdef ENTROPY_STATS
active_section = 1;
#endif
@@ -2825,7 +2812,7 @@
{
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);
--- a/vp8/encoder/encodeframe.c
+++ b/vp8/encoder/encodeframe.c
@@ -1982,6 +1982,7 @@
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
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -3418,6 +3418,7 @@
}
#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 @@
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 @@
// 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 @@
#endif
#if !CONFIG_COMPRED
+//#if 1
update_rd_ref_frame_probs(cpi);
#endif
--- a/vp8/encoder/onyx_int.h
+++ b/vp8/encoder/onyx_int.h
@@ -519,7 +519,7 @@
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];
--
⑨