Commit 156b221a authored by Paul Wilkins's avatar Paul Wilkins

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
parent 45e49e6e
......@@ -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))
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->ref_frame = (MV_REFERENCE_FRAME)((int)mbmi->ref_frame + (int)(1 + vp8_read(bc, pbi->prob_gf)));
mbmi->mode =
xd->segment_feature_data[mbmi->segment_id][SEG_LVL_MODE];
}
vp8_find_near_mvs(&pbi->mb, mi, &nearest, &nearby, &best_mv, rct, mbmi->ref_frame, pbi->common.ref_frame_sign_bias);
vp8_mv_ref_probs(mv_ref_p, rct);
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
}
......@@ -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
switch (mode) /* new, split require MVs */
{
case NEWMV:
write_split(w, mi->partitioning);
#ifdef ENTROPY_STATS
active_section = 5;
#endif
do
write_mv(w, &mi->mv.as_mv, &best_mv, mvc);
break;
case SPLITMV:
{
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);
int j = 0;
#ifdef MODE_STATS
++count_mb_seg [mi->partitioning];
#endif
write_sub_mv_ref(w, blockmode, vp8_sub_mv_ref_prob2 [mv_contz]);
write_split(w, mi->partitioning);
if (blockmode == NEW4X4)
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;
......
......@@ -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;
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;
}
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,7 +852,44 @@ 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)
{
......@@ -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)
......
......@@ -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++;