Commit 2370d440 authored by Paul Wilkins's avatar Paul Wilkins Committed by On2 (Google) Code Review
Browse files

Merge "Segmentation: Reference frames" into experimental

parents ab9a4ce0 87ff8620
...@@ -93,9 +93,9 @@ DECLARE_ALIGNED(64, short, vp8_default_zig_zag_mask_8x8[64]);//int64_t ...@@ -93,9 +93,9 @@ DECLARE_ALIGNED(64, short, vp8_default_zig_zag_mask_8x8[64]);//int64_t
#endif #endif
#if CONFIG_SEGFEATURES #if CONFIG_SEGFEATURES
const int vp8_mb_feature_data_bits[SEG_LVL_MAX] = {7, 6, 2, 3, 4, 2}; const int vp8_seg_feature_data_bits[SEG_LVL_MAX] = {7, 6, 4, 4, 4, 2};
#else #else
const int vp8_mb_feature_data_bits[SEG_LVL_MAX] = {7, 6}; const int vp8_seg_feature_data_bits[SEG_LVL_MAX] = {7, 6};
#endif #endif
/* Array indices are identical to previously-existing CONTEXT_NODE indices */ /* Array indices are identical to previously-existing CONTEXT_NODE indices */
......
...@@ -106,7 +106,7 @@ extern short vp8_default_zig_zag_mask[16]; ...@@ -106,7 +106,7 @@ extern short vp8_default_zig_zag_mask[16];
extern DECLARE_ALIGNED(64, const int, vp8_default_zig_zag1d_8x8[64]); extern DECLARE_ALIGNED(64, const int, vp8_default_zig_zag1d_8x8[64]);
extern short vp8_default_zig_zag_mask_8x8[64];//int64_t extern short vp8_default_zig_zag_mask_8x8[64];//int64_t
#endif #endif
extern const int vp8_mb_feature_data_bits[SEG_LVL_MAX]; extern const int vp8_seg_feature_data_bits[SEG_LVL_MAX];
void vp8_coef_tree_initialize(void); void vp8_coef_tree_initialize(void);
#endif #endif
...@@ -53,6 +53,55 @@ int is_segfeature_signed( SEG_LVL_FEATURES feature_id ) ...@@ -53,6 +53,55 @@ int is_segfeature_signed( SEG_LVL_FEATURES feature_id )
return ( segfeaturedata_signed[feature_id] ); return ( segfeaturedata_signed[feature_id] );
} }
void clear_segdata( MACROBLOCKD *xd,
int segment_id,
SEG_LVL_FEATURES feature_id)
{
xd->segment_feature_data[segment_id][feature_id] = 0;
}
void set_segdata( MACROBLOCKD *xd,
int segment_id,
SEG_LVL_FEATURES feature_id,
int seg_data )
{
xd->segment_feature_data[segment_id][feature_id] = seg_data;
}
int get_segdata( MACROBLOCKD *xd,
int segment_id,
SEG_LVL_FEATURES feature_id )
{
return xd->segment_feature_data[segment_id][feature_id];
}
void clear_segref( MACROBLOCKD *xd, int segment_id )
{
xd->segment_feature_data[segment_id][SEG_LVL_REF_FRAME] = 0;
}
void set_segref( MACROBLOCKD *xd,
int segment_id,
MV_REFERENCE_FRAME ref_frame )
{
xd->segment_feature_data[segment_id][SEG_LVL_REF_FRAME] |=
(1 << ref_frame);
}
int check_segref( MACROBLOCKD *xd,
int segment_id,
MV_REFERENCE_FRAME ref_frame )
{
return ( xd->segment_feature_data[segment_id][SEG_LVL_REF_FRAME] &
(1 << ref_frame) ) ? 1 : 0;
}
int check_segref_inter(MACROBLOCKD *xd, int segment_id)
{
return ( xd->segment_feature_data[segment_id][SEG_LVL_REF_FRAME] &
~(1 << INTRA_FRAME) ) ? 1 : 0;
}
// TBD? Functions to read and write segment data with range / validity checking // TBD? Functions to read and write segment data with range / validity checking
#endif #endif
...@@ -30,5 +30,31 @@ void disable_segfeature( MACROBLOCKD *xd, ...@@ -30,5 +30,31 @@ void disable_segfeature( MACROBLOCKD *xd,
int is_segfeature_signed( SEG_LVL_FEATURES feature_id ); int is_segfeature_signed( SEG_LVL_FEATURES feature_id );
void clear_segdata( MACROBLOCKD *xd,
int segment_id,
SEG_LVL_FEATURES feature_id);
void set_segdata( MACROBLOCKD *xd,
int segment_id,
SEG_LVL_FEATURES feature_id,
int seg_data );
int get_segdata( MACROBLOCKD *xd,
int segment_id,
SEG_LVL_FEATURES feature_id );
void clear_segref( MACROBLOCKD *xd, int segment_id );
void set_segref( MACROBLOCKD *xd,
int segment_id,
MV_REFERENCE_FRAME ref_frame );
int check_segref( MACROBLOCKD *xd,
int segment_id,
MV_REFERENCE_FRAME ref_frame );
int check_segref_inter(MACROBLOCKD *xd, int segment_id);
#endif /* __INC_SEG_COMMON_H__ */ #endif /* __INC_SEG_COMMON_H__ */
...@@ -232,26 +232,25 @@ static void read_mvcontexts(vp8_reader *bc, MV_CONTEXT *mvc) ...@@ -232,26 +232,25 @@ static void read_mvcontexts(vp8_reader *bc, MV_CONTEXT *mvc)
// Read the referncence frame // Read the referncence frame
static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi, static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi,
vp8_reader *const bc,
unsigned char segment_id ) unsigned char segment_id )
{ {
MV_REFERENCE_FRAME ref_frame; MV_REFERENCE_FRAME ref_frame;
int seg_ref_active;
#if CONFIG_SEGFEATURES #if CONFIG_SEGFEATURES
MACROBLOCKD *const xd = &pbi->mb; MACROBLOCKD *const xd = &pbi->mb;
// Is the segment level refernce frame feature enabled for this segment seg_ref_active = segfeature_active( xd,
if ( segfeature_active( xd, segment_id, SEG_LVL_REF_FRAME ) ) segment_id,
{ SEG_LVL_REF_FRAME );
ref_frame = #else
xd->segment_feature_data[segment_id][SEG_LVL_REF_FRAME]; seg_ref_active = 0;
}
else
#endif #endif
// Per MB read of the reference frame // Segment reference frame features not available
if ( !seg_ref_active )
{ {
vp8_reader *const bc = &pbi->bc;
ref_frame = ref_frame =
(MV_REFERENCE_FRAME) vp8_read(bc, pbi->prob_intra); (MV_REFERENCE_FRAME) vp8_read(bc, pbi->prob_intra);
...@@ -265,6 +264,79 @@ static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi, ...@@ -265,6 +264,79 @@ static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi,
} }
} }
#if CONFIG_SEGFEATURES
// Segment reference frame features are enabled
else
{
// If there are no inter reference frames enabled we can set INTRA
if ( !check_segref_inter(xd, segment_id) )
{
ref_frame = INTRA_FRAME;
}
else
{
// Else if there are both intra and inter options we need to read
// the inter / intra flag, else mark as inter.
if ( check_segref( xd, segment_id, INTRA_FRAME ) )
ref_frame = (MV_REFERENCE_FRAME) vp8_read(bc, pbi->prob_intra);
else
ref_frame = 1; // note this unchanged = LAST
if ( ref_frame )
{
// Now consider last vs (golden or alt) flag....
// If Last is not enabled
if ( !check_segref( xd, segment_id, LAST_FRAME ) )
{
// If not golden then it must be altref
if (!check_segref( xd, segment_id, GOLDEN_FRAME ))
{
ref_frame = ALTREF_FRAME;
}
// Not Altref therefore must be Golden
else if (!check_segref( xd, segment_id,
ALTREF_FRAME ))
{
ref_frame = GOLDEN_FRAME;
}
// Else we must read bit to decide.
else
{
ref_frame = (MV_REFERENCE_FRAME)((int)ref_frame +
(int)(1 + vp8_read(bc, pbi->prob_gf)));
}
}
// Both last and at least one of alt or golden are enabled
else if ( check_segref( xd, segment_id, GOLDEN_FRAME ) ||
check_segref( xd, segment_id, ALTREF_FRAME ) )
{
// Read flag to indicate (golden or altref) vs last
if (vp8_read(bc, pbi->prob_last))
{
// If not golden then it must be altref
if (!check_segref( xd, segment_id, GOLDEN_FRAME ))
{
ref_frame = ALTREF_FRAME;
}
// Not Altref therefore must be Golden
else if (!check_segref( xd, segment_id,
ALTREF_FRAME ))
{
ref_frame = GOLDEN_FRAME;
}
else
{
ref_frame = (MV_REFERENCE_FRAME)((int)ref_frame +
(int)(1 + vp8_read(bc, pbi->prob_gf)));
}
}
// ELSE LAST
}
}
}
}
#endif
return (MV_REFERENCE_FRAME)ref_frame; return (MV_REFERENCE_FRAME)ref_frame;
} }
...@@ -458,7 +530,7 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, ...@@ -458,7 +530,7 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
} }
// Read the reference frame // Read the reference frame
mbmi->ref_frame = read_ref_frame( pbi, mbmi->segment_id ); mbmi->ref_frame = read_ref_frame( pbi, bc, mbmi->segment_id );
// If reference frame is an Inter frame // If reference frame is an Inter frame
if (mbmi->ref_frame) if (mbmi->ref_frame)
...@@ -634,15 +706,22 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi, ...@@ -634,15 +706,22 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
} }
else else
{ {
#if CONFIG_SEGFEATURES
// TBD HANDLE INTRA MODE CASE
#endif
/* required for left and above block mv */ /* required for left and above block mv */
mbmi->mv.as_int = 0; mbmi->mv.as_int = 0;
/* MB is intra coded */ #if CONFIG_SEGFEATURES
if ((mbmi->mode = (MB_PREDICTION_MODE) vp8_read_ymode(bc, pbi->common.fc.ymode_prob)) == B_PRED) if ( segfeature_active( xd, mbmi->segment_id, SEG_LVL_MODE ) )
mbmi->mode = (MB_PREDICTION_MODE)
get_segdata( xd, mbmi->segment_id, SEG_LVL_MODE );
else
#endif
{
mbmi->mode = (MB_PREDICTION_MODE)
vp8_read_ymode(bc, pbi->common.fc.ymode_prob);
}
// If MB mode is BPRED read the block modes
if (mbmi->mode == B_PRED)
{ {
int j = 0; int j = 0;
do do
......
...@@ -883,7 +883,7 @@ int vp8_decode_frame(VP8D_COMP *pbi) ...@@ -883,7 +883,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
int mb_row; int mb_row;
int i, j, k, l; int i, j, k, l;
const int *const mb_feature_data_bits = vp8_mb_feature_data_bits; const int *const mb_feature_data_bits = vp8_seg_feature_data_bits;
int corrupt_tokens = 0; int corrupt_tokens = 0;
int prev_independent_partitions = pbi->independent_partitions; int prev_independent_partitions = pbi->independent_partitions;
......
...@@ -873,6 +873,90 @@ static void write_mb_features(vp8_writer *w, const MB_MODE_INFO *mi, const MACRO ...@@ -873,6 +873,90 @@ static void write_mb_features(vp8_writer *w, const MB_MODE_INFO *mi, const MACRO
} }
} }
// This function encodes the reference frame
static void encode_ref_frame( vp8_writer *const w,
MACROBLOCKD *xd,
int segment_id,
MV_REFERENCE_FRAME rf,
int prob_intra_coded,
int prob_last_coded,
int prob_gf_coded )
{
int seg_ref_active;
#if CONFIG_SEGFEATURES
seg_ref_active = segfeature_active( xd,
segment_id,
SEG_LVL_REF_FRAME );
#else
seg_ref_active = 0;
#endif
// No segment features or segment reference frame featuure is disabled
if ( !seg_ref_active )
{
if (rf == INTRA_FRAME)
{
vp8_write(w, 0, prob_intra_coded);
}
else /* inter coded */
{
vp8_write(w, 1, prob_intra_coded);
if (rf == LAST_FRAME)
{
vp8_write(w, 0, prob_last_coded);
}
else
{
vp8_write(w, 1, prob_last_coded);
vp8_write(w, (rf == GOLDEN_FRAME) ? 0 : 1, prob_gf_coded);
}
}
}
#if CONFIG_SEGFEATURES
else
{
if (rf == INTRA_FRAME)
{
// This MB intra coded. If inter also allowed we must code
// an explicit inter/intra flag.
if ( check_segref_inter( xd, segment_id ) )
vp8_write(w, 0, prob_intra_coded);
}
else /* inter coded */
{
// If intra also allowed we must code an explicit intra/inter flag.
if ( check_segref( xd, segment_id, INTRA_FRAME ) )
vp8_write(w, 1, prob_intra_coded);
if (rf == LAST_FRAME)
{
// If GOLDEN or ALTREF allowed we must code explicit flag.
if ( check_segref( xd, segment_id, GOLDEN_FRAME ) ||
check_segref( xd, segment_id, ALTREF_FRAME ) )
{
vp8_write(w, 0, prob_last_coded);
}
}
else
{
// if LAST is allowed we must code explicit flag
if ( check_segref( xd, segment_id, LAST_FRAME ) )
{
vp8_write(w, 1, prob_last_coded);
}
// if GOLDEN and ALTREF allowed we must code an explicit flag
if ( check_segref( xd, segment_id, GOLDEN_FRAME ) &&
check_segref( xd, segment_id, ALTREF_FRAME ) )
{
vp8_write(w, (rf == GOLDEN_FRAME) ? 0 : 1, prob_gf_coded);
}
}
}
}
#endif
}
static void pack_inter_mode_mvs(VP8_COMP *const cpi) static void pack_inter_mode_mvs(VP8_COMP *const cpi)
{ {
...@@ -969,14 +1053,16 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) ...@@ -969,14 +1053,16 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
const MB_PREDICTION_MODE mode = mi->mode; const MB_PREDICTION_MODE mode = mi->mode;
const int segment_id = mi->segment_id; const int segment_id = mi->segment_id;
//MACROBLOCKD *xd = &cpi->mb.e_mbd;
// Distance of Mb to the various image edges. // Distance of Mb to the various image edges.
// These specified to 8th pel as they are always compared to MV values that are in 1/8th pel units // These specified to 8th pel as they are always compared to MV values that are in 1/8th pel units
xd->mb_to_left_edge = -((mb_col * 16) << 3); xd->mb_to_left_edge = -((mb_col * 16) << 3);
xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3; xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
xd->mb_to_top_edge = -((mb_row * 16)) << 3; xd->mb_to_top_edge = -((mb_row * 16)) << 3;
xd->mb_to_bottom_edge = ((pc->mb_rows - 1 - mb_row) * 16) << 3; xd->mb_to_bottom_edge = ((pc->mb_rows - 1 - mb_row) * 16) << 3;
// Make sure the MacroBlockD mode info pointer is set correctly
xd->mode_info_context = m;
#if CONFIG_SEGMENTATION #if CONFIG_SEGMENTATION
xd->up_available = (mb_row != 0); xd->up_available = (mb_row != 0);
xd->left_available = (mb_col != 0); xd->left_available = (mb_col != 0);
...@@ -1036,20 +1122,23 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) ...@@ -1036,20 +1122,23 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
vp8_encode_bool(w, mi->mb_skip_coeff, prob_skip_false); vp8_encode_bool(w, mi->mb_skip_coeff, prob_skip_false);
} }
// Encode the reference frame.
encode_ref_frame( w, xd, segment_id, rf,
cpi->prob_intra_coded,
prob_last_coded, prob_gf_coded );
if (rf == INTRA_FRAME) if (rf == INTRA_FRAME)
{ {
#if CONFIG_SEGFEATURES #ifdef ENTROPY_STATS
// Is the segment coding of reference frame enabled
if ( !segfeature_active( xd, segment_id, SEG_LVL_REF_FRAME ) )
#endif
{
vp8_write(w, 0, cpi->prob_intra_coded);
}
#ifdef ENTROPY_STATS
active_section = 6; active_section = 6;
#endif #endif
#if CONFIG_SEGFEATURES
if ( !segfeature_active( xd, segment_id, SEG_LVL_MODE ) )
write_ymode(w, mode, pc->fc.ymode_prob);
#else
write_ymode(w, mode, pc->fc.ymode_prob); write_ymode(w, mode, pc->fc.ymode_prob);
#endif
if (mode == B_PRED) if (mode == B_PRED)
{ {
...@@ -1062,28 +1151,11 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) ...@@ -1062,28 +1151,11 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
write_uv_mode(w, mi->uv_mode, pc->fc.uv_mode_prob); write_uv_mode(w, mi->uv_mode, pc->fc.uv_mode_prob);
} }
else /* inter coded */ else
{ {
int_mv best_mv; int_mv best_mv;
vp8_prob mv_ref_p [VP8_MVREFS-1]; vp8_prob mv_ref_p [VP8_MVREFS-1];
#if CONFIG_SEGFEATURES
// Test to see if segment level coding of ref frame is enabled
if ( !segfeature_active( xd, segment_id, SEG_LVL_REF_FRAME ) )
#endif
{
vp8_write(w, 1, cpi->prob_intra_coded);
if (rf == LAST_FRAME)
vp8_write(w, 0, prob_last_coded);
else
{
vp8_write(w, 1, prob_last_coded);
vp8_write(w, (rf == GOLDEN_FRAME)
? 0 : 1, prob_gf_coded);
}
}
{ {
int_mv n1, n2; int_mv n1, n2;
int ct[4]; int ct[4];
...@@ -1103,10 +1175,13 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) ...@@ -1103,10 +1175,13 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
#if CONFIG_SEGFEATURES #if CONFIG_SEGFEATURES
// Is the segment coding of reference frame enabled // Is the segment coding of reference frame enabled
if ( !segfeature_active( xd, segment_id, SEG_LVL_MODE ) ) if ( !segfeature_active( xd, segment_id, SEG_LVL_MODE ) )
#endif
{ {
write_mv_ref(w, mode, mv_ref_p); write_mv_ref(w, mode, mv_ref_p);
}
#else
write_mv_ref(w, mode, mv_ref_p);
#endif
{
switch (mode) /* new, split require MVs */ switch (mode) /* new, split require MVs */
{ {
case NEWMV: case NEWMV:
...@@ -1913,7 +1988,7 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size) ...@@ -1913,7 +1988,7 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size)
oh.version = pc->version; oh.version = pc->version;
oh.first_partition_length_in_bytes = 0; oh.first_partition_length_in_bytes = 0;
mb_feature_data_bits = vp8_mb_feature_data_bits; mb_feature_data_bits = vp8_seg_feature_data_bits;
cx_data += 3; cx_data += 3;
#if defined(SECTIONBITS_OUTPUT) #if defined(SECTIONBITS_OUTPUT)
......
...@@ -1584,11 +1584,12 @@ int vp8cx_encode_inter_macroblock ...@@ -1584,11 +1584,12 @@ int vp8cx_encode_inter_macroblock
int intra_error = 0; int intra_error = 0;
int rate; int rate;
int distortion; int distortion;
int segment_id = xd->mode_info_context->mbmi.segment_id;
x->skip = 0; x->skip = 0;
if (xd->segmentation_enabled) if (xd->segmentation_enabled)
x->encode_breakout = cpi->segment_encode_breakout[xd->mode_info_context->mbmi.segment_id]; x->encode_breakout = cpi->segment_encode_breakout[segment_id];
else else
x->encode_breakout = cpi->oxcf.encode_breakout; x->encode_breakout = cpi->oxcf.encode_breakout;
...@@ -1650,7 +1651,7 @@ int vp8cx_encode_inter_macroblock ...@@ -1650,7 +1651,7 @@ int vp8cx_encode_inter_macroblock
if (cpi->cyclic_refresh_mode_enabled) if (cpi->cyclic_refresh_mode_enabled)
{ {
// Clear segment_id back to 0 if not coded (last frame 0,0) // Clear segment_id back to 0 if not coded (last frame 0,0)
if ( (xd->mode_info_context->mbmi.segment_id == 1) && if ( (segment_id == 1) &&
( (xd->mode_info_context->mbmi.ref_frame != LAST_FRAME) || ( (xd->mode_info_context->mbmi.ref_frame != LAST_FRAME) ||
(xd->mode_info_context->mbmi.mode != ZEROMV) ) ) (xd->mode_info_context->mbmi.mode != ZEROMV) ) )
{ {
...@@ -1711,10 +1712,20 @@ int vp8cx_encode_inter_macroblock ...@@ -1711,10 +1712,20 @@ int vp8cx_encode_inter_macroblock
} }
#if CONFIG_SEGFEATURES #if CONFIG_SEGFEATURES
// Dont increment usage count if ref frame coded at segment level
if ( !segfeature_active( xd, xd->mode_info_context->mbmi.segment_id, // If we have just a single reference frame coded for a segment then
SEG_LVL_REF_FRAME ) ) // 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 ) ||
( ( 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]++;