// 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);
(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) )
{
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);
}
}
+#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);
// 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);
vp8_write(w, (rf == GOLDEN_FRAME) ? 0 : 1, cm->prob_gf_coded);
}
}
+#endif
}
//#if CONFIG_SEGFEATURES
// Else use the segment
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;
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;
}
}
+#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);
#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
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
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
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;
}
//#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)
//#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"
{
static int init_done = 0;
-
if (!init_done)
{
vp8_scale_machine_specific_config();
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);
// 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);
// 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));
}
}
+#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)
#endif
}
-
+#endif
// 1 = key, 0 = inter
static int decide_key_frame(VP8_COMP *cpi)
}
+#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,
}
#endif
+#if !CONFIG_COMPRED
update_rd_ref_frame_probs(cpi);
+#endif
// Test code for new segment features
init_seg_features( cpi );
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);
#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];
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];
//#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)
#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);
}
}
+#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,
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++)
{
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;
}
#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)
{
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),