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
This commit is contained in:
parent
f0459549a6
commit
58ec6fe8c3
@ -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
|
||||
|
@ -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
|
||||
|
@ -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) );
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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];
|
||||
|
Loading…
x
Reference in New Issue
Block a user