Segment coding of mode and reference frame.

Proof of concept test code that encodes mode and reference
frame data at the segment level.

Decode-able bit stream but some issues not yet resolved.
As it this helps a little on a couple of clips but hurts on most as
the basis for segmentation is unsound.

To build and test, configure with
--enable-experimental --enable-segfeatures

Change-Id: I22a60774f69273523fb152db8c31f4b10b07c7f4
This commit is contained in:
Paul Wilkins 2011-09-30 16:45:16 +01:00
parent 45e49e6e19
commit 156b221a7f
6 changed files with 511 additions and 118 deletions

View File

@ -200,6 +200,43 @@ static void read_mvcontexts(vp8_reader *bc, MV_CONTEXT *mvc)
while (++i < 2);
}
// Read the referncence frame
static MV_REFERENCE_FRAME read_ref_frame( VP8D_COMP *pbi,
unsigned char segment_id )
{
MV_REFERENCE_FRAME ref_frame;
#if CONFIG_SEGFEATURES
MACROBLOCKD *const xd = &pbi->mb;
// Is the segment level refernce frame feature enabled for this segment
if ( xd->segment_feature_mask[segment_id] & (0x01 << SEG_LVL_REF_FRAME) )
{
ref_frame =
xd->segment_feature_data[segment_id][SEG_LVL_REF_FRAME];
}
else
#endif
// Per MB read of the reference frame
{
vp8_reader *const bc = &pbi->bc;
ref_frame =
(MV_REFERENCE_FRAME) vp8_read(bc, pbi->prob_intra);
if (ref_frame)
{
if (vp8_read(bc, pbi->prob_last))
{
ref_frame = (MV_REFERENCE_FRAME)((int)ref_frame +
(int)(1 + vp8_read(bc, pbi->prob_gf)));
}
}
}
return (MV_REFERENCE_FRAME)ref_frame;
}
static MB_PREDICTION_MODE read_mv_ref(vp8_reader *bc, const vp8_prob *p)
{
@ -296,8 +333,9 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
vp8_reader *const bc = & pbi->bc;
MV_CONTEXT *const mvc = pbi->common.fc.mvc;
const int mis = pbi->common.mode_info_stride;
#if CONFIG_SEGMENTATION
MACROBLOCKD *const xd = & pbi->mb;
#if CONFIG_SEGMENTATION
int sum;
int index = mb_row * pbi->common.mb_cols + mb_col;
#endif
@ -307,24 +345,24 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
int mb_to_top_edge;
int mb_to_bottom_edge;
mb_to_top_edge = pbi->mb.mb_to_top_edge;
mb_to_bottom_edge = pbi->mb.mb_to_bottom_edge;
mb_to_top_edge = xd->mb_to_top_edge;
mb_to_bottom_edge = xd->mb_to_bottom_edge;
mb_to_top_edge -= LEFT_TOP_MARGIN;
mb_to_bottom_edge += RIGHT_BOTTOM_MARGIN;
mbmi->need_to_clamp_mvs = 0;
/* 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
*/
pbi->mb.mb_to_left_edge =
xd->mb_to_left_edge =
mb_to_left_edge = -((mb_col * 16) << 3);
mb_to_left_edge -= LEFT_TOP_MARGIN;
pbi->mb.mb_to_right_edge =
xd->mb_to_right_edge =
mb_to_right_edge = ((pbi->common.mb_cols - 1 - mb_col) * 16) << 3;
mb_to_right_edge += RIGHT_BOTTOM_MARGIN;
/* If required read in new segmentation data for this MB */
if (pbi->mb.update_mb_segmentation_map)
if (xd->update_mb_segmentation_map)
{
#if CONFIG_SEGMENTATION
if (xd->temporal_update)
@ -343,7 +381,7 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
}
else
{
vp8_read_mb_features(bc, &mi->mbmi, &pbi->mb);
vp8_read_mb_features(bc, &mi->mbmi, xd);
mbmi->segment_flag = 1;
pbi->segmentation_map[index] = mbmi->segment_id;
}
@ -351,12 +389,12 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
}
else
{
vp8_read_mb_features(bc, &mi->mbmi, &pbi->mb);
vp8_read_mb_features(bc, &mi->mbmi, xd);
pbi->segmentation_map[index] = mbmi->segment_id;
}
index++;
#else
vp8_read_mb_features(bc, &mi->mbmi, &pbi->mb);
vp8_read_mb_features(bc, &mi->mbmi, xd);
#endif
}
@ -367,23 +405,38 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
else
mbmi->mb_skip_coeff = 0;
if ((mbmi->ref_frame = (MV_REFERENCE_FRAME) vp8_read(bc, pbi->prob_intra))) /* inter MB */
// Read the reference frame
mbmi->ref_frame = read_ref_frame( pbi, mbmi->segment_id );
// If reference frame is an Inter frame
if (mbmi->ref_frame)
{
int rct[4];
vp8_prob mv_ref_p [VP8_MVREFS-1];
int_mv nearest, nearby, best_mv;
vp8_prob mv_ref_p [VP8_MVREFS-1];
if (vp8_read(bc, pbi->prob_last))
{
mbmi->ref_frame = (MV_REFERENCE_FRAME)((int)mbmi->ref_frame + (int)(1 + vp8_read(bc, pbi->prob_gf)));
}
vp8_find_near_mvs(&pbi->mb, mi, &nearest, &nearby, &best_mv, rct, mbmi->ref_frame, pbi->common.ref_frame_sign_bias);
vp8_find_near_mvs(xd, mi, &nearest, &nearby, &best_mv, rct,
mbmi->ref_frame, pbi->common.ref_frame_sign_bias);
vp8_mv_ref_probs(mv_ref_p, rct);
#if CONFIG_SEGFEATURES
// Is the segment level mode feature enabled for this segment
if ( xd->segment_feature_mask[mbmi->segment_id] &
(0x01 << SEG_LVL_MODE) )
{
mbmi->mode =
xd->segment_feature_data[mbmi->segment_id][SEG_LVL_MODE];
}
else
{
mbmi->mode = read_mv_ref(bc, mv_ref_p);
}
#else
mbmi->mode = read_mv_ref(bc, mv_ref_p);
#endif
mbmi->uv_mode = DC_PRED;
switch (mbmi->mode = read_mv_ref(bc, mv_ref_p))
switch (mbmi->mode)
{
case SPLITMV:
{
@ -530,6 +583,10 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
}
else
{
#if CONFIG_SEGFEATURES
// TBD HANDLE INTRA MODE CASE
#endif
/* required for left and above block mv */
mbmi->mv.as_int = 0;
@ -554,6 +611,14 @@ void vp8_decode_mode_mvs(VP8D_COMP *pbi)
MODE_INFO *mi = pbi->common.mi;
int mb_row = -1;
#if CONFIG_SEGFEATURES
#if 0
FILE *statsfile;
statsfile = fopen("decsegmap.stt", "a");
fprintf(statsfile, "\n" );
#endif
#endif
mb_mode_mv_init(pbi);
#if CONFIG_QIMODE
@ -577,6 +642,12 @@ void vp8_decode_mode_mvs(VP8D_COMP *pbi)
mb_to_bottom_edge = ((pbi->common.mb_rows - 1 - mb_row) * 16) << 3;
mb_to_bottom_edge += RIGHT_BOTTOM_MARGIN;
#if CONFIG_SEGFEATURES
#if 0
fprintf(statsfile, "\n" );
#endif
#endif
while (++mb_col < pbi->common.mb_cols)
{
#if CONFIG_ERROR_CONCEALMENT
@ -617,9 +688,23 @@ void vp8_decode_mode_mvs(VP8D_COMP *pbi)
}
#endif
#if CONFIG_SEGFEATURES
#if 0
fprintf(statsfile, "%2d%2d%2d ",
mi->mbmi.segment_id, mi->mbmi.ref_frame, mi->mbmi.mode );
#endif
#endif
mi++; /* next macroblock */
}
// printf("\n");
mi++; /* skip left predictor each row */
}
#if CONFIG_SEGFEATURES
#if 0
fclose(statsfile);
#endif
#endif
}

View File

@ -896,7 +896,13 @@ 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 (!(cpi->prob_intra_coded = rf_intra * 255 / (rf_intra + rf_inter)))
#if CONFIG_SEGFEATURES
cpi->prob_intra_coded = (rf_intra + rf_inter)
? rf_intra * 255 / (rf_intra + rf_inter) : 1;
#else
cpi->prob_intra_coded = rf_intra * 255 / (rf_intra + rf_inter);
#endif
if (!cpi->prob_intra_coded)
cpi->prob_intra_coded = 1;
prob_last_coded = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;
@ -1010,7 +1016,15 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
if (rf == INTRA_FRAME)
{
vp8_write(w, 0, cpi->prob_intra_coded);
#if CONFIG_SEGFEATURES
// Is the segment coding of reference frame enabled
if ( !( xd->segment_feature_mask[mi->segment_id] &
(0x01 << SEG_LVL_REF_FRAME) ) )
#endif
{
vp8_write(w, 0, cpi->prob_intra_coded);
}
#ifdef ENTROPY_STATS
active_section = 6;
#endif
@ -1032,14 +1046,22 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
int_mv best_mv;
vp8_prob mv_ref_p [VP8_MVREFS-1];
vp8_write(w, 1, cpi->prob_intra_coded);
if (rf == LAST_FRAME)
vp8_write(w, 0, prob_last_coded);
else
#if CONFIG_SEGFEATURES
// Is the segment coding of reference frame enabled
if ( !( xd->segment_feature_mask[mi->segment_id] &
(0x01 << SEG_LVL_REF_FRAME) ) )
#endif
{
vp8_write(w, 1, prob_last_coded);
vp8_write(w, (rf == GOLDEN_FRAME) ? 0 : 1, prob_gf_coded);
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);
}
}
{
@ -1052,73 +1074,79 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi)
#ifdef ENTROPY_STATS
accum_mv_refs(mode, ct);
#endif
}
#ifdef ENTROPY_STATS
active_section = 3;
#endif
write_mv_ref(w, mode, mv_ref_p);
switch (mode) /* new, split require MVs */
{
case NEWMV:
#ifdef ENTROPY_STATS
active_section = 5;
#if CONFIG_SEGFEATURES
// Is the segment coding of reference frame enabled
if ( !( xd->segment_feature_mask[mi->segment_id] &
(0x01 << SEG_LVL_MODE) ) )
#endif
write_mv(w, &mi->mv.as_mv, &best_mv, mvc);
break;
case SPLITMV:
{
int j = 0;
write_mv_ref(w, mode, mv_ref_p);
#ifdef MODE_STATS
++count_mb_seg [mi->partitioning];
#endif
write_split(w, mi->partitioning);
do
switch (mode) /* new, split require MVs */
{
B_PREDICTION_MODE blockmode;
int_mv blockmv;
const int *const L = vp8_mbsplits [mi->partitioning];
int k = -1; /* first block in subset j */
int mv_contz;
int_mv leftmv, abovemv;
case NEWMV:
blockmode = cpi->mb.partition_info->bmi[j].mode;
blockmv = cpi->mb.partition_info->bmi[j].mv;
#if CONFIG_DEBUG
while (j != L[++k])
if (k >= 16)
assert(0);
#else
while (j != L[++k]);
#endif
leftmv.as_int = left_block_mv(m, k);
abovemv.as_int = above_block_mv(m, k, mis);
mv_contz = vp8_mv_cont(&leftmv, &abovemv);
#ifdef ENTROPY_STATS
active_section = 5;
#endif
write_sub_mv_ref(w, blockmode, vp8_sub_mv_ref_prob2 [mv_contz]);
write_mv(w, &mi->mv.as_mv, &best_mv, mvc);
break;
if (blockmode == NEW4X4)
case SPLITMV:
{
int j = 0;
#ifdef MODE_STATS
++count_mb_seg [mi->partitioning];
#endif
write_split(w, mi->partitioning);
do
{
#ifdef ENTROPY_STATS
active_section = 11;
#endif
write_mv(w, &blockmv.as_mv, &best_mv, (const MV_CONTEXT *) mvc);
B_PREDICTION_MODE blockmode;
int_mv blockmv;
const int *const L = vp8_mbsplits [mi->partitioning];
int k = -1; /* first block in subset j */
int mv_contz;
int_mv leftmv, abovemv;
blockmode = cpi->mb.partition_info->bmi[j].mode;
blockmv = cpi->mb.partition_info->bmi[j].mv;
#if CONFIG_DEBUG
while (j != L[++k])
if (k >= 16)
assert(0);
#else
while (j != L[++k]);
#endif
leftmv.as_int = left_block_mv(m, k);
abovemv.as_int = above_block_mv(m, k, mis);
mv_contz = vp8_mv_cont(&leftmv, &abovemv);
write_sub_mv_ref(w, blockmode, vp8_sub_mv_ref_prob2 [mv_contz]);
if (blockmode == NEW4X4)
{
#ifdef ENTROPY_STATS
active_section = 11;
#endif
write_mv(w, &blockmv.as_mv, &best_mv, (const MV_CONTEXT *) mvc);
}
}
while (++j < cpi->mb.partition_info->count);
}
while (++j < cpi->mb.partition_info->count);
}
break;
default:
break;
default:
break;
}
}
}
@ -1448,7 +1476,13 @@ int vp8_estimate_entropy_savings(VP8_COMP *cpi)
if (cpi->common.frame_type != KEY_FRAME)
{
if (!(new_intra = rf_intra * 255 / (rf_intra + rf_inter)))
#if CONFIG_SEGFEATURES
new_intra = (rf_intra + rf_inter)
? rf_intra * 255 / (rf_intra + rf_inter) : 1;
#else
new_intra = rf_intra * 255 / (rf_intra + rf_inter);
#endif
if (!new_intra)
new_intra = 1;
new_last = rf_inter ? (rfct[LAST_FRAME] * 255) / rf_inter : 128;

View File

@ -717,27 +717,51 @@ void encode_mb_row(VP8_COMP *cpi,
if ((xd->mode_info_context->mbmi.mode == ZEROMV) && (xd->mode_info_context->mbmi.ref_frame == LAST_FRAME))
cpi->inter_zz_count ++;
// Special case code for cyclic refresh
// If cyclic update enabled then copy xd->mbmi.segment_id; (which may have been updated based on mode
// during vp8cx_encode_inter_macroblock()) back into the global sgmentation map
if (cpi->cyclic_refresh_mode_enabled && xd->segmentation_enabled)
// Actions required if segmentation enabled
if ( xd->segmentation_enabled )
{
cpi->segmentation_map[map_index+mb_col] = xd->mode_info_context->mbmi.segment_id;
// If the block has been refreshed mark it as clean (the magnitude of the -ve influences how long it will be before we consider another refresh):
// Else if it was coded (last frame 0,0) and has not already been refreshed then mark it as a candidate for cleanup next time (marked 0)
// else mark it as dirty (1).
if (xd->mode_info_context->mbmi.segment_id)
cpi->cyclic_refresh_map[map_index+mb_col] = -1;
else if ((xd->mode_info_context->mbmi.mode == ZEROMV) && (xd->mode_info_context->mbmi.ref_frame == LAST_FRAME))
// Special case code for cyclic refresh
// If cyclic update enabled then copy xd->mbmi.segment_id;
// (which may have been updated based on mode during
// vp8cx_encode_inter_macroblock()) back into the global
// segmentation map
if (cpi->cyclic_refresh_mode_enabled)
{
if (cpi->cyclic_refresh_map[map_index+mb_col] == 1)
cpi->cyclic_refresh_map[map_index+mb_col] = 0;
}
else
cpi->cyclic_refresh_map[map_index+mb_col] = 1;
cpi->segmentation_map[map_index+mb_col] =
xd->mode_info_context->mbmi.segment_id;
// If the block has been refreshed mark it as clean (the
// magnitude of the -ve influences how long it will be
// before we consider another refresh):
// Else if it was coded (last frame 0,0) and has not
// already been refreshed then mark it as a candidate
// for cleanup next time (marked 0)
// else mark it as dirty (1).
if (xd->mode_info_context->mbmi.segment_id)
cpi->cyclic_refresh_map[map_index+mb_col] = -1;
else if ((xd->mode_info_context->mbmi.mode == ZEROMV) &&
(xd->mode_info_context->mbmi.ref_frame ==
LAST_FRAME))
{
if (cpi->cyclic_refresh_map[map_index+mb_col] == 1)
cpi->cyclic_refresh_map[map_index+mb_col] = 0;
}
else
cpi->cyclic_refresh_map[map_index+mb_col] = 1;
}
#if CONFIG_SEGFEATURES
else if ( cm->refresh_alt_ref_frame &&
(cm->frame_type != KEY_FRAME) )
{
// Update the global segmentation map to reflect
// the segment choice made for this MB.
cpi->segmentation_map[map_index+mb_col] =
xd->mode_info_context->mbmi.segment_id;
}
#endif
}
}
cpi->tplist[mb_row].stop = *tp;
@ -828,8 +852,45 @@ void encode_mb_row(VP8_COMP *cpi,
sem_post(&cpi->h_event_end_encoding); /* signal frame encoding end */
}
#endif
#if CONFIG_SEGFEATURES
// debug output
#if 0
{
FILE *statsfile;
statsfile = fopen("segmap2.stt", "a");
fprintf(statsfile, "\n" );
fclose(statsfile);
}
#endif
#endif
}
#if CONFIG_SEGFEATURES
// Funtion to test out new segment features
void segfeature_test_function(VP8_COMP *cpi, MACROBLOCKD * xd)
{
VP8_COMMON *const cm = & cpi->common;
// Only update segment map for a frame that is an arf but not a kf.
if ( cm->refresh_alt_ref_frame && (cm->frame_type != KEY_FRAME) )
{
// Test code to code features at the segment level
if ( (xd->mode_info_context->mbmi.mode ==
cpi->segment_feature_data[1][SEG_LVL_MODE]) &&
(xd->mode_info_context->mbmi.ref_frame ==
cpi->segment_feature_data[1][SEG_LVL_REF_FRAME]) )
{
xd->mode_info_context->mbmi.segment_id = 1;
}
else
xd->mode_info_context->mbmi.segment_id = 0;
}
}
#endif
void init_encode_frame_mb_context(VP8_COMP *cpi)
{
MACROBLOCK *const x = & cpi->mb;
@ -927,6 +988,7 @@ void vp8_encode_frame(VP8_COMP *cpi)
MACROBLOCKD *const xd = & x->e_mbd;
TOKENEXTRA *tp = cpi->tok;
#if CONFIG_SEGMENTATION
int segment_counts[MAX_MB_SEGMENTS + SEEK_SEGID];
int prob[3];
@ -936,6 +998,19 @@ void vp8_encode_frame(VP8_COMP *cpi)
#endif
int totalrate;
#if CONFIG_SEGFEATURES
// debug output
#if 0
{
FILE *statsfile;
statsfile = fopen("segmap2.stt", "a");
fprintf(statsfile, "\n" );
fclose(statsfile);
}
#endif
#endif
vpx_memset(segment_counts, 0, sizeof(segment_counts));
totalrate = 0;
@ -1307,8 +1382,16 @@ void vp8_encode_frame(VP8_COMP *cpi)
cpi->prob_gf_coded = 1;
}
}
#if CONFIG_SEGFEATURES
else
{
// Trap case where cpi->count_mb_ref_frame_usage[] blank.
cpi->prob_intra_coded = 63;
cpi->prob_last_coded = 128;
cpi->prob_gf_coded = 128;
}
#endif
}
#if 0
// Keep record of the total distortion this time around for future use
cpi->last_frame_distortion = cpi->frame_distortion;
@ -1599,8 +1682,9 @@ int vp8cx_encode_inter_macroblock
if (cpi->cyclic_refresh_mode_enabled)
{
// Clear segment_id back to 0 if not coded (last frame 0,0)
if ((xd->mode_info_context->mbmi.segment_id == 1) &&
((xd->mode_info_context->mbmi.ref_frame != LAST_FRAME) || (xd->mode_info_context->mbmi.mode != ZEROMV)))
if ( (xd->mode_info_context->mbmi.segment_id == 1) &&
( (xd->mode_info_context->mbmi.ref_frame != LAST_FRAME) ||
(xd->mode_info_context->mbmi.mode != ZEROMV) ) )
{
xd->mode_info_context->mbmi.segment_id = 0;
@ -1608,6 +1692,26 @@ int vp8cx_encode_inter_macroblock
vp8cx_mb_init_quantizer(cpi, x);
}
}
#if CONFIG_SEGFEATURES
else
{
segfeature_test_function(cpi, xd);
#if 0
// Debug output
{
FILE *statsfile;
statsfile = fopen("segmap2.stt", "a");
fprintf(statsfile, "%2d%2d%2d ",
xd->mode_info_context->mbmi.segment_id,
xd->mode_info_context->mbmi.ref_frame,
xd->mode_info_context->mbmi.mode );
fclose(statsfile);
}
#endif
}
#endif
}
{
@ -1638,7 +1742,15 @@ int vp8cx_encode_inter_macroblock
vp8_update_zbin_extra(cpi, x);
}
#if 0
//#if CONFIG_SEGFEATURES
// Test code using segment 1 only.
// Dont increment count if ref frame coded at segment level
if ( (xd->mode_info_context->mbmi.segment_id != 1) )
cpi->count_mb_ref_frame_usage[xd->mode_info_context->mbmi.ref_frame]++;
#else
cpi->count_mb_ref_frame_usage[xd->mode_info_context->mbmi.ref_frame] ++;
#endif
#if CONFIG_T8X8
if (xd->segmentation_enabled)

View File

@ -434,14 +434,6 @@ static void set_segmentation_map(VP8_PTR ptr, unsigned char *segmentation_map)
cpi->mb.e_mbd.update_mb_segmentation_data = 1;
}
// The values given for each segment can be either deltas (from the default value chosen for the frame) or absolute values.
//
// Valid range for abs values is (0-127 for SEG_LVL_ALT_Q) , (0-63 for SEGMENT_ALT_LF)
// Valid range for delta values are (+/-127 for SEG_LVL_ALT_Q) , (+/-63 for SEGMENT_ALT_LF)
//
// abs_delta = SEGMENT_DELTADATA (deltas) abs_delta = SEGMENT_ABSDATA (use the absolute values given).
//
//
static void set_segment_data(VP8_PTR ptr, signed char *feature_data, unsigned char abs_delta)
{
VP8_COMP *cpi = (VP8_COMP *)(ptr);
@ -514,6 +506,99 @@ static void segmentation_test_function(VP8_PTR ptr)
}
#if CONFIG_SEGFEATURES
static void init_seg_features(VP8_COMP *cpi)
{
VP8_COMMON *cm = &cpi->common;
MACROBLOCKD *mbd = &cpi->mb.e_mbd;
// For now at least dont enable seg features alongside cyclic refresh.
if (cpi->cyclic_refresh_mode_enabled)
return;
// No updates for key frames
if ( cm->frame_type == KEY_FRAME )
{
cpi->mb.e_mbd.update_mb_segmentation_map = 0;
cpi->mb.e_mbd.update_mb_segmentation_data = 0;
}
// Arf but not a key frame.
else if ( cm->refresh_alt_ref_frame )
{
// Clear down the global segmentation map
vpx_memset( cpi->segmentation_map, 0, (cm->mb_rows * cm->mb_cols));
// Activate segmentation.
enable_segmentation((VP8_PTR)cpi);
// For now set GF, (0,0) MV in segment 1
cpi->segment_feature_data[1][SEG_LVL_REF_FRAME] = LAST_FRAME;
cpi->segment_feature_data[1][SEG_LVL_MODE] = ZEROMV;
mbd->segment_feature_data[1][SEG_LVL_REF_FRAME] = LAST_FRAME;
mbd->segment_feature_data[1][SEG_LVL_MODE] = ZEROMV;
// Enable target features is the segment feature mask
mbd->segment_feature_mask[1] |= (0x01 << SEG_LVL_REF_FRAME);
mbd->segment_feature_mask[1] |= (0x01 << SEG_LVL_MODE);
}
else
{
// Special case where we are coding over the top of a previous
// alt ref frame
if ( cpi->is_src_frame_alt_ref )
{
if ( cpi->source_alt_ref_pending )
{
cpi->mb.e_mbd.update_mb_segmentation_data = 1;
cpi->segment_feature_data[1][SEG_LVL_REF_FRAME] = ALTREF_FRAME;
mbd->segment_feature_data[1][SEG_LVL_REF_FRAME] = ALTREF_FRAME;
}
else
{
vpx_memset( cpi->segmentation_map, 0,
(cm->mb_rows * cm->mb_cols));
cpi->mb.e_mbd.update_mb_segmentation_map = 1;
cpi->mb.e_mbd.update_mb_segmentation_data = 1;
}
}
else
{
cpi->mb.e_mbd.update_mb_segmentation_data = 0;
}
}
}
// DEBUG: Print out the segment id of each MB in the current frame.
static void print_seg_map(VP8_COMP *cpi)
{
VP8_COMMON *cm = & cpi->common;
int row,col;
int map_index = 0;
FILE *statsfile;
statsfile = fopen("segmap.stt", "a");
fprintf(statsfile, "%10d\n",
cm->current_video_frame );
for ( row = 0; row < cpi->common.mb_rows; row++ )
{
for ( col = 0; col < cpi->common.mb_cols; col++ )
{
fprintf(statsfile, "%10d",
cpi->segmentation_map[map_index]);
map_index++;
}
fprintf(statsfile, "\n");
}
fprintf(statsfile, "\n");
fclose(statsfile);
}
#endif
// A simple function to cyclically refresh the background at a lower Q
static void cyclic_background_refresh(VP8_COMP *cpi, int Q, int lf_adjustment)
{
@ -3401,13 +3486,6 @@ static void encode_frame_to_data_rate
// Clear down mmx registers to allow floating point in what follows
vp8_clear_system_state();
// Test code for segmentation of gf/arf (0,0)
//segmentation_test_function((VP8_PTR) cpi);
#if CONFIG_SEGMENTATION
cpi->mb.e_mbd.segmentation_enabled = 1;
cpi->mb.e_mbd.update_mb_segmentation_map = 1;
#endif
if (cpi->compressor_speed == 2)
{
if(cpi->oxcf.auto_key && cm->frame_type != KEY_FRAME)
@ -3472,9 +3550,23 @@ static void encode_frame_to_data_rate
cm->frame_type = KEY_FRAME;
}
// Set default state for segment and mode based loop filter update flags
cpi->mb.e_mbd.update_mb_segmentation_map = 0;
cpi->mb.e_mbd.update_mb_segmentation_data = 0;
// Test code for segmentation of gf/arf (0,0)
//segmentation_test_function((VP8_PTR) cpi);
#if CONFIG_SEGMENTATION
cpi->mb.e_mbd.segmentation_enabled = 1;
cpi->mb.e_mbd.update_mb_segmentation_map = 1;
#else
#if CONFIG_SEGFEATURES
// Test code for new segment features
init_seg_features( cpi );
#else
// Set default state for segment update flags
cpi->mb.e_mbd.update_mb_segmentation_map = 0;
cpi->mb.e_mbd.update_mb_segmentation_data = 0;
#endif
#endif
// Set default state for segment based loop filter update flags
cpi->mb.e_mbd.mode_ref_lf_delta_update = 0;
// Set various flags etc to special state if it is a key frame
@ -4533,6 +4625,13 @@ static void encode_frame_to_data_rate
}
}
#endif
#if CONFIG_SEGFEATURES
#if 0
// Debug stats for segment feature experiments.
print_seg_map(cpi);
#endif
#endif
// If this was a kf or Gf note the Q

View File

@ -409,6 +409,7 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
BLOCKD *d = &x->e_mbd.block[0];
MACROBLOCKD *xd = &x->e_mbd;
MB_MODE_INFO best_mbmode;
VP8_COMMON *cm = & cpi->common;
int_mv best_ref_mv;
int_mv mode_mv[MB_MODE_COUNT];
@ -514,6 +515,38 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
if (skip_mode[x->e_mbd.mode_info_context->mbmi.ref_frame])
continue;
#if CONFIG_SEGFEATURES
// Experimental use of Segment features.
if ( !cm->refresh_alt_ref_frame )
{
unsigned char segment_id = xd->mode_info_context->mbmi.segment_id;
int feature_mask = xd->segment_feature_mask[segment_id];
if ( (feature_mask & (0x01 << SEG_LVL_REF_FRAME)) &&
( x->e_mbd.mode_info_context->mbmi.ref_frame !=
cpi->segment_feature_data[segment_id][SEG_LVL_REF_FRAME]))
{
continue;
}
if ( (feature_mask & (0x01 << SEG_LVL_MODE)) &&
( this_mode !=
cpi->segment_feature_data[segment_id][SEG_LVL_MODE]))
{
continue;
}
}
#else
// Only consider ZEROMV/ALTREF_FRAME for alt ref frame,
// unless ARNR filtering is enabled in which case we want
// an unfiltered alternative
if (cpi->is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0))
{
if (this_mode != ZEROMV ||
x->e_mbd.mode_info_context->mbmi.ref_frame != ALTREF_FRAME)
continue;
}
// Check to see if the testing frequency for this mode is at its max
// If so then prevent it from being tested and increase the threshold for its testing
if (cpi->mode_test_hit_counts[mode_index] && (cpi->mode_check_freq[mode_index] > 1))
@ -532,6 +565,7 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
continue;
}
}
#endif
// We have now reached the point where we are going to test the current mode so increment the counter for the number of times it has been tested
cpi->mode_test_hit_counts[mode_index] ++;
@ -564,6 +598,7 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
memcpy(mdcounts, MDCounts[x->e_mbd.mode_info_context->mbmi.ref_frame], sizeof(mdcounts));
}
#if !CONFIG_SEGFEATURES
// Only consider ZEROMV/ALTREF_FRAME for alt ref frame,
// unless ARNR filtering is enabled in which case we want
// an unfiltered alternative
@ -572,6 +607,7 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
if (this_mode != ZEROMV || x->e_mbd.mode_info_context->mbmi.ref_frame != ALTREF_FRAME)
continue;
}
#endif
switch (this_mode)
{

View File

@ -1993,6 +1993,7 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
BLOCK *b = &x->block[0];
BLOCKD *d = &x->e_mbd.block[0];
MACROBLOCKD *xd = &x->e_mbd;
VP8_COMMON *cm = &cpi->common;
union b_mode_info best_bmodes[16];
MB_MODE_INFO best_mbmode;
PARTITION_INFO best_partition;
@ -2119,14 +2120,38 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
x->e_mbd.mode_info_context->mbmi.ref_frame = vp8_ref_frame_order[mode_index];
#if CONFIG_SEGFEATURES
// Experimental use of Segment features.
if ( !cm->refresh_alt_ref_frame )
{
unsigned char segment_id = xd->mode_info_context->mbmi.segment_id;
int feature_mask = xd->segment_feature_mask[segment_id];
if ( (feature_mask & (0x01 << SEG_LVL_REF_FRAME)) &&
( x->e_mbd.mode_info_context->mbmi.ref_frame !=
cpi->segment_feature_data[segment_id][SEG_LVL_REF_FRAME]))
{
continue;
}
if ( (feature_mask & (0x01 << SEG_LVL_MODE)) &&
( this_mode !=
cpi->segment_feature_data[segment_id][SEG_LVL_MODE]))
{
continue;
}
}
#else
// Only consider ZEROMV/ALTREF_FRAME for alt ref frame,
// unless ARNR filtering is enabled in which case we want
// an unfiltered alternative
if (cpi->is_src_frame_alt_ref && (cpi->oxcf.arnr_max_frames == 0))
{
if (this_mode != ZEROMV || x->e_mbd.mode_info_context->mbmi.ref_frame != ALTREF_FRAME)
if (this_mode != ZEROMV ||
x->e_mbd.mode_info_context->mbmi.ref_frame != ALTREF_FRAME)
continue;
}
#endif
/* everything but intra */
if (x->e_mbd.mode_info_context->mbmi.ref_frame)
@ -2141,6 +2166,7 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
lf_or_gf = frame_lf_or_gf[x->e_mbd.mode_info_context->mbmi.ref_frame];
}
#if !CONFIG_SEGFEATURES
// Check to see if the testing frequency for this mode is at its max
// If so then prevent it from being tested and increase the threshold for its testing
if (cpi->mode_test_hit_counts[mode_index] && (cpi->mode_check_freq[mode_index] > 1))
@ -2161,6 +2187,7 @@ void vp8_rd_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset, int
// We have now reached the point where we are going to test the current mode so increment the counter for the number of times it has been tested
cpi->mode_test_hit_counts[mode_index] ++;
#endif
// Experimental code. Special case for gf and arf zeromv modes. Increase zbin size to supress noise
if (cpi->zbin_mode_boost_enabled)