vp8e - entropy stats per frame type

Change-Id: I4168eb6ea22ae541471738a7a3453e7d52059275
This commit is contained in:
Jim Bankoski 2011-12-09 16:56:18 -08:00
parent 254889cdfc
commit 6de67cd6e8
6 changed files with 124 additions and 216 deletions

View File

@ -878,7 +878,28 @@ static void write_mb_features(vp8_writer *w, const MB_MODE_INFO *mi, const MACRO
}
}
}
void vp8_convert_rfct_to_prob(VP8_COMP *const cpi)
{
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];
// Calculate the probabilities used to code the ref frame based on useage
if (!(cpi->prob_intra_coded = rf_intra * 255 / (rf_intra + rf_inter)))
cpi->prob_intra_coded = 1;
cpi->prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
if (!cpi->prob_last_coded)
cpi->prob_last_coded = 1;
cpi->prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
if (!cpi->prob_gf_coded)
cpi->prob_gf_coded = 1;
}
static void pack_inter_mode_mvs(VP8_COMP *const cpi)
{
@ -886,36 +907,17 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
vp8_writer *const w = cpi->bc;
const MV_CONTEXT *mvc = pc->fc.mvc;
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, *ms;
const int mis = pc->mode_info_stride;
int mb_row = -1;
int prob_last_coded;
int prob_gf_coded;
int prob_skip_false = 0;
ms = pc->mi - 1;
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 (!(cpi->prob_intra_coded = rf_intra * 255 / (rf_intra + rf_inter)))
cpi->prob_intra_coded = 1;
prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
if (!prob_last_coded)
prob_last_coded = 1;
prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
if (!prob_gf_coded)
prob_gf_coded = 1;
vp8_convert_rfct_to_prob(cpi);
#ifdef ENTROPY_STATS
active_section = 1;
@ -936,8 +938,8 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
}
vp8_write_literal(w, cpi->prob_intra_coded, 8);
vp8_write_literal(w, prob_last_coded, 8);
vp8_write_literal(w, prob_gf_coded, 8);
vp8_write_literal(w, cpi->prob_last_coded, 8);
vp8_write_literal(w, cpi->prob_gf_coded, 8);
update_mbintra_mode_probs(cpi);
@ -999,11 +1001,11 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
vp8_write(w, 1, cpi->prob_intra_coded);
if (rf == LAST_FRAME)
vp8_write(w, 0, prob_last_coded);
vp8_write(w, 0, cpi->prob_last_coded);
else
{
vp8_write(w, 1, prob_last_coded);
vp8_write(w, (rf == GOLDEN_FRAME) ? 0 : 1, prob_gf_coded);
vp8_write(w, 1, cpi->prob_last_coded);
vp8_write(w, (rf == GOLDEN_FRAME) ? 0 : 1, cpi->prob_gf_coded);
}
{
@ -1355,6 +1357,24 @@ static int default_coef_context_savings(VP8_COMP *cpi)
return savings;
}
void vp8_calc_ref_frame_costs(int *ref_frame_cost,
int prob_intra,
int prob_last,
int prob_garf
)
{
ref_frame_cost[INTRA_FRAME] = vp8_cost_zero(prob_intra);
ref_frame_cost[LAST_FRAME] = vp8_cost_one(prob_intra)
+ vp8_cost_zero(prob_last);
ref_frame_cost[GOLDEN_FRAME] = vp8_cost_one(prob_intra)
+ vp8_cost_one(prob_last)
+ vp8_cost_zero(prob_garf);
ref_frame_cost[ALTREF_FRAME] = vp8_cost_one(prob_intra)
+ vp8_cost_one(prob_last)
+ vp8_cost_one(prob_garf);
}
int vp8_estimate_entropy_savings(VP8_COMP *cpi)
{
int savings = 0;
@ -1362,7 +1382,7 @@ int vp8_estimate_entropy_savings(VP8_COMP *cpi)
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];
int new_intra, new_last, gf_last, oldtotal, newtotal;
int new_intra, new_last, new_garf, oldtotal, newtotal;
int ref_frame_cost[MAX_REF_FRAMES];
vp8_clear_system_state(); //__asm emms;
@ -1374,19 +1394,11 @@ int vp8_estimate_entropy_savings(VP8_COMP *cpi)
new_last = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
gf_last = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
new_garf = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
// new costs
ref_frame_cost[INTRA_FRAME] = vp8_cost_zero(new_intra);
ref_frame_cost[LAST_FRAME] = vp8_cost_one(new_intra)
+ vp8_cost_zero(new_last);
ref_frame_cost[GOLDEN_FRAME] = vp8_cost_one(new_intra)
+ vp8_cost_one(new_last)
+ vp8_cost_zero(gf_last);
ref_frame_cost[ALTREF_FRAME] = vp8_cost_one(new_intra)
+ vp8_cost_one(new_last)
+ vp8_cost_one(gf_last);
vp8_calc_ref_frame_costs(ref_frame_cost,new_intra,new_last,new_garf);
newtotal =
rfct[INTRA_FRAME] * ref_frame_cost[INTRA_FRAME] +
@ -1396,15 +1408,8 @@ int vp8_estimate_entropy_savings(VP8_COMP *cpi)
// old costs
ref_frame_cost[INTRA_FRAME] = vp8_cost_zero(cpi->prob_intra_coded);
ref_frame_cost[LAST_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ vp8_cost_zero(cpi->prob_last_coded);
ref_frame_cost[GOLDEN_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ vp8_cost_one(cpi->prob_last_coded)
+ vp8_cost_zero(cpi->prob_gf_coded);
ref_frame_cost[ALTREF_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ vp8_cost_one(cpi->prob_last_coded)
+ vp8_cost_one(cpi->prob_gf_coded);
vp8_calc_ref_frame_costs(ref_frame_cost,cpi->prob_intra_coded,
cpi->prob_last_coded,cpi->prob_gf_coded);
oldtotal =
rfct[INTRA_FRAME] * ref_frame_cost[INTRA_FRAME] +

View File

@ -39,7 +39,12 @@
#define IF_RTCD(x) NULL
#endif
extern void vp8_stuff_mb(VP8_COMP *cpi, MACROBLOCKD *x, TOKENEXTRA **t) ;
extern void vp8_calc_ref_frame_costs(int *ref_frame_cost,
int prob_intra,
int prob_last,
int prob_garf
);
extern void vp8_convert_rfct_to_prob(VP8_COMP *const cpi);
extern void vp8cx_initialize_me_consts(VP8_COMP *cpi, int QIndex);
extern void vp8_auto_select_speed(VP8_COMP *cpi);
extern void vp8cx_init_mbrthread_data(VP8_COMP *cpi,
@ -636,55 +641,23 @@ void init_encode_frame_mb_context(VP8_COMP *cpi)
vpx_memset(cm->above_context, 0,
sizeof(ENTROPY_CONTEXT_PLANES) * cm->mb_cols);
xd->ref_frame_cost[INTRA_FRAME] = vp8_cost_zero(cpi->prob_intra_coded);
// Special case treatment when GF and ARF are not sensible options for reference
if (cpi->ref_frame_flags == VP8_LAST_FLAG)
{
xd->ref_frame_cost[LAST_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ vp8_cost_zero(255);
xd->ref_frame_cost[GOLDEN_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ vp8_cost_one(255)
+ vp8_cost_zero(128);
xd->ref_frame_cost[ALTREF_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ vp8_cost_one(255)
+ vp8_cost_one(128);
}
vp8_calc_ref_frame_costs(xd->ref_frame_cost,
cpi->prob_intra_coded,255,128);
else if ((cpi->oxcf.number_of_layers > 1) &&
(cpi->ref_frame_flags == VP8_GOLD_FLAG))
{
xd->ref_frame_cost[LAST_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ vp8_cost_zero(1);
xd->ref_frame_cost[GOLDEN_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ vp8_cost_one(1)
+ vp8_cost_zero(255);
xd->ref_frame_cost[ALTREF_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ vp8_cost_one(1)
+ vp8_cost_one(255);
}
vp8_calc_ref_frame_costs(xd->ref_frame_cost,
cpi->prob_intra_coded,1,255);
else if ((cpi->oxcf.number_of_layers > 1) &&
(cpi->ref_frame_flags == VP8_ALT_FLAG))
{
xd->ref_frame_cost[LAST_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ vp8_cost_zero(1);
xd->ref_frame_cost[GOLDEN_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ vp8_cost_one(1)
+ vp8_cost_zero(1);
xd->ref_frame_cost[ALTREF_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ vp8_cost_one(1)
+ vp8_cost_one(1);
}
vp8_calc_ref_frame_costs(xd->ref_frame_cost,
cpi->prob_intra_coded,1,1);
else
{
xd->ref_frame_cost[LAST_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ vp8_cost_zero(cpi->prob_last_coded);
xd->ref_frame_cost[GOLDEN_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ vp8_cost_one(cpi->prob_last_coded)
+ vp8_cost_zero(cpi->prob_gf_coded);
xd->ref_frame_cost[ALTREF_FRAME] = vp8_cost_one(cpi->prob_intra_coded)
+ vp8_cost_one(cpi->prob_last_coded)
+ vp8_cost_one(cpi->prob_gf_coded);
}
vp8_calc_ref_frame_costs(xd->ref_frame_cost,
cpi->prob_intra_coded,
cpi->prob_last_coded,
cpi->prob_gf_coded);
xd->fullpixel_mask = 0xffffffff;
if(cm->full_pixel)
@ -966,31 +939,7 @@ void vp8_encode_frame(VP8_COMP *cpi)
if ((cm->frame_type != KEY_FRAME) && ((cpi->oxcf.number_of_layers > 1) ||
(!cm->refresh_alt_ref_frame && !cm->refresh_golden_frame)))
{
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 ((rf_intra + rf_inter) > 0)
{
cpi->prob_intra_coded = (rf_intra * 255) / (rf_intra + rf_inter);
if (cpi->prob_intra_coded < 1)
cpi->prob_intra_coded = 1;
if ((cm->frames_since_golden > 0) || cpi->source_alt_ref_active)
{
cpi->prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
if (cpi->prob_last_coded < 1)
cpi->prob_last_coded = 1;
cpi->prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
if (cpi->prob_gf_coded < 1)
cpi->prob_gf_coded = 1;
}
}
vp8_convert_rfct_to_prob(cpi);
}
#if 0

View File

@ -70,6 +70,7 @@ extern void vp8_yv12_copy_src_frame_func_neon(YV12_BUFFER_CONFIG *src_ybc, YV12_
#endif
int vp8_estimate_entropy_savings(VP8_COMP *cpi);
int vp8_calc_ss_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest, const vp8_variance_rtcd_vtable_t *rtcd);
extern void vp8_temporal_filter_prepare_c(VP8_COMP *cpi, int distance);
@ -2997,47 +2998,6 @@ static void update_rd_ref_frame_probs(VP8_COMP *cpi)
{
VP8_COMMON *cm = &cpi->common;
#if 0
const int *const rfct = cpi->recent_ref_frame_usage;
const int rf_intra = rfct[INTRA_FRAME];
const int rf_inter = rfct[LAST_FRAME] + rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME];
if (cm->frame_type == KEY_FRAME)
{
cpi->prob_intra_coded = 255;
cpi->prob_last_coded = 128;
cpi->prob_gf_coded = 128;
}
else if (!(rf_intra + rf_inter))
{
// This is a trap in case this function is called with cpi->recent_ref_frame_usage[] blank.
cpi->prob_intra_coded = 63;
cpi->prob_last_coded = 128;
cpi->prob_gf_coded = 128;
}
else
{
cpi->prob_intra_coded = (rf_intra * 255) / (rf_intra + rf_inter);
if (cpi->prob_intra_coded < 1)
cpi->prob_intra_coded = 1;
if ((cm->frames_since_golden > 0) || cpi->source_alt_ref_active)
{
cpi->prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
if (cpi->prob_last_coded < 1)
cpi->prob_last_coded = 1;
cpi->prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
if (cpi->prob_gf_coded < 1)
cpi->prob_gf_coded = 1;
}
}
#else
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];
@ -3050,59 +3010,9 @@ static void update_rd_ref_frame_probs(VP8_COMP *cpi)
}
else if (!(rf_intra + rf_inter))
{
if (cpi->oxcf.number_of_layers > 1)
{
if (cpi->ref_frame_flags == VP8_LAST_FLAG)
{
cpi->prob_intra_coded = 63;
cpi->prob_last_coded = 255;
cpi->prob_gf_coded = 128;
}
else if (cpi->ref_frame_flags == VP8_GOLD_FLAG)
{
cpi->prob_intra_coded = 63;
cpi->prob_last_coded = 1;
cpi->prob_gf_coded = 255;
}
else if (cpi->ref_frame_flags == VP8_ALT_FLAG)
{
cpi->prob_intra_coded = 63;
cpi->prob_last_coded = 1;
cpi->prob_gf_coded = 1;
}
else
{
cpi->prob_intra_coded = 63;
cpi->prob_last_coded = 128;
cpi->prob_gf_coded = 128;
}
}
else
{
// This is a trap in case this function is called with
// cpi->recent_ref_frame_usage[] blank.
cpi->prob_intra_coded = 63;
cpi->prob_last_coded = 128;
cpi->prob_gf_coded = 128;
}
}
else
{
cpi->prob_intra_coded = (rf_intra * 255) / (rf_intra + rf_inter);
if (cpi->prob_intra_coded < 1)
cpi->prob_intra_coded = 1;
cpi->prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
if (cpi->prob_last_coded < 1)
cpi->prob_last_coded = 1;
cpi->prob_gf_coded = (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME])
? (rfct[GOLDEN_FRAME] * 255) / (rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME]) : 128;
if (cpi->prob_gf_coded < 1)
cpi->prob_gf_coded = 1;
cpi->prob_intra_coded = 63;
cpi->prob_last_coded = 128;
cpi->prob_gf_coded = 128;
}
// update reference frame costs since we can do better than what we got last frame.
@ -3117,7 +3027,6 @@ static void update_rd_ref_frame_probs(VP8_COMP *cpi)
else if (cpi->common.frames_since_golden == 0)
{
cpi->prob_last_coded = 214;
cpi->prob_gf_coded = 1;
}
else if (cpi->common.frames_since_golden == 1)
{
@ -3126,14 +3035,14 @@ static void update_rd_ref_frame_probs(VP8_COMP *cpi)
}
else if (cpi->source_alt_ref_active)
{
//int dist = cpi->common.frames_till_alt_ref_frame + cpi->common.frames_since_golden;
cpi->prob_gf_coded -= 20;
if (cpi->prob_gf_coded < 10)
cpi->prob_gf_coded = 10;
}
if (!cpi->source_alt_ref_active)
cpi->prob_gf_coded = 255;
}
#endif
}
@ -5216,6 +5125,17 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon
vpx_memcpy(&cm->fc, &cm->lfc, sizeof(cm->fc));
}
// Save the contexts separately for alt ref, gold and last.
// (TODO jbb -> Optimize this with pointers to avoid extra copies. )
if(cm->refresh_alt_ref_frame)
vpx_memcpy(&cpi->lfc_a, &cm->fc, sizeof(cm->fc));
if(cm->refresh_golden_frame)
vpx_memcpy(&cpi->lfc_g, &cm->fc, sizeof(cm->fc));
if(cm->refresh_last_frame)
vpx_memcpy(&cpi->lfc_n, &cm->fc, sizeof(cm->fc));
// if its a dropped frame honor the requests on subsequent frames
if (*size > 0)
{

View File

@ -568,6 +568,11 @@ typedef struct VP8_COMP
int base_skip_false_prob[128];
FRAME_CONTEXT lfc_n; /* last frame entropy */
FRAME_CONTEXT lfc_a; /* last alt ref entropy */
FRAME_CONTEXT lfc_g; /* last gold ref entropy */
struct twopass_rc
{
unsigned int section_intra_rating;

View File

@ -304,6 +304,8 @@ void vp8_setup_key_frame(VP8_COMP *cpi)
// Setup for Key frame:
vp8_default_coef_probs(& cpi->common);
vp8_kf_default_bmode_probs(cpi->common.kf_bmode_prob);
vpx_memcpy(cpi->common.fc.mvc, vp8_default_mv_context, sizeof(vp8_default_mv_context));
@ -314,6 +316,12 @@ void vp8_setup_key_frame(VP8_COMP *cpi)
vpx_memset(cpi->common.fc.pre_mvc, 0, sizeof(cpi->common.fc.pre_mvc)); //initialize pre_mvc to all zero.
// Make sure we initialize separate contexts for altref,gold, and normal.
// TODO shouldn't need 3 different copies of structure to do this!
vpx_memcpy(&cpi->lfc_a, &cpi->common.fc, sizeof(cpi->common.fc));
vpx_memcpy(&cpi->lfc_g, &cpi->common.fc, sizeof(cpi->common.fc));
vpx_memcpy(&cpi->lfc_n, &cpi->common.fc, sizeof(cpi->common.fc));
//cpi->common.filter_level = 0; // Reset every key frame.
cpi->common.filter_level = cpi->common.base_qindex * 3 / 8 ;

View File

@ -288,12 +288,33 @@ void vp8_initialize_rd_consts(VP8_COMP *cpi, int Qvalue)
}
}
fill_token_costs(
cpi->mb.token_costs,
(const vp8_prob( *)[8][3][11]) cpi->common.fc.coef_probs
);
{
// build token cost array for the type of frame we have now
FRAME_CONTEXT *l = &cpi->lfc_n;
vp8_init_mode_costs(cpi);
if(cpi->common.refresh_alt_ref_frame)
l = &cpi->lfc_a;
else if(cpi->common.refresh_golden_frame)
l = &cpi->lfc_g;
fill_token_costs(
cpi->mb.token_costs,
(const vp8_prob( *)[8][3][11]) l->coef_probs
);
/*
fill_token_costs(
cpi->mb.token_costs,
(const vp8_prob( *)[8][3][11]) cpi->common.fc.coef_probs);
*/
// TODO make these mode costs depend on last,alt or gold too. (jbb)
vp8_init_mode_costs(cpi);
// TODO figure onnnnuut why making mv cost frame type dependent didn't help (jbb)
//vp8_build_component_cost_table(cpi->mb.mvcost, (const MV_CONTEXT *) l->mvc, flags);
}
}