From bf25d4ad7f5f9c7b11894be140783da8ee640494 Mon Sep 17 00:00:00 2001 From: Paul Wilkins Date: Fri, 11 Nov 2011 10:10:06 +0000 Subject: SEGMENTATION experiment: Some initial cleanup to aid testing and debug. Pull code to choose temporal or spatial encoding out of encodeframe.c into a dedicated function in segmentation.c. For now disable broken temporal mode. Move the coding of "temporal_update" flag and only transmit if segment map update is indicated. Rename the functions read_mb_features() and write_mb_features() to read_mb_segid() and read_mb_segid() as they only read and write the macroblock segment id not any of the features. Change-Id: Ib75118520b1144c24d35fdfc6ce46106803cabcf --- vp8/decoder/decodemv.c | 15 +++--- vp8/decoder/decodframe.c | 11 +++- vp8/encoder/bitstream.c | 26 ++++++---- vp8/encoder/encodeframe.c | 106 +++----------------------------------- vp8/encoder/onyx_int.h | 6 +++ vp8/encoder/segmentation.c | 126 +++++++++++++++++++++++++++++++++++++++++++++ vp8/encoder/segmentation.h | 5 ++ 7 files changed, 176 insertions(+), 119 deletions(-) (limited to 'vp8') diff --git a/vp8/decoder/decodemv.c b/vp8/decoder/decodemv.c index d279ebaec..e13fd6f09 100644 --- a/vp8/decoder/decodemv.c +++ b/vp8/decoder/decodemv.c @@ -63,7 +63,9 @@ static int vp8_read_uv_mode(vp8_reader *bc, const vp8_prob *p) return i; } -static void vp8_read_mb_features(vp8_reader *r, MB_MODE_INFO *mi, MACROBLOCKD *x) +// This function reads the current macro block's segnment id to from bitstream +// It should only be called if a segment map update is indicated. +static void vp8_read_mb_segid(vp8_reader *r, MB_MODE_INFO *mi, MACROBLOCKD *x) { /* Is segmentation enabled */ if (x->segmentation_enabled && x->update_mb_segmentation_map) @@ -90,7 +92,7 @@ static void vp8_kfread_modes(VP8D_COMP *pbi, MODE_INFO *m, int mb_row, int mb_co m->mbmi.segment_id = 0; if (pbi->mb.update_mb_segmentation_map) - vp8_read_mb_features(bc, &m->mbmi, &pbi->mb); + vp8_read_mb_segid(bc, &m->mbmi, &pbi->mb); //#if CONFIG_SEGFEATURES if ( pbi->common.mb_no_coeff_skip && @@ -419,9 +421,6 @@ static void mb_mode_mv_init(VP8D_COMP *pbi) } read_mvcontexts(bc, mvc); -#if CONFIG_SEGMENTATION - xd->temporal_update = vp8_read_bit(bc); -#endif } } @@ -480,7 +479,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, xd); + vp8_read_mb_segid(bc, &mi->mbmi, xd); mbmi->segment_flag = 1; pbi->segmentation_map[index] = mbmi->segment_id; } @@ -488,12 +487,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, xd); + vp8_read_mb_segid(bc, &mi->mbmi, xd); pbi->segmentation_map[index] = mbmi->segment_id; } index++; #else - vp8_read_mb_features(bc, &mi->mbmi, xd); + vp8_read_mb_segid(bc, &mi->mbmi, xd); #endif } diff --git a/vp8/decoder/decodframe.c b/vp8/decoder/decodframe.c index 963939cf0..5ba499155 100644 --- a/vp8/decoder/decodframe.c +++ b/vp8/decoder/decodframe.c @@ -1004,8 +1004,17 @@ int vp8_decode_frame(VP8D_COMP *pbi) xd->segmentation_enabled = (unsigned char)vp8_read_bit(bc); if (xd->segmentation_enabled) { - /* Signal whether or not the segmentation map is being explicitly updated this frame. */ + // Read whether or not the segmentation map is being explicitly + // updated this frame. xd->update_mb_segmentation_map = (unsigned char)vp8_read_bit(bc); + +#if CONFIG_SEGMENTATION + // If so what method will be used. + if ( xd->update_mb_segmentation_map ) + xd->temporal_update = (unsigned char)vp8_read_bit(bc); +#endif + + // Is the segment data being updated xd->update_mb_segmentation_data = (unsigned char)vp8_read_bit(bc); if (xd->update_mb_segmentation_data) diff --git a/vp8/encoder/bitstream.c b/vp8/encoder/bitstream.c index 40e845fda..19ec6d622 100644 --- a/vp8/encoder/bitstream.c +++ b/vp8/encoder/bitstream.c @@ -824,7 +824,10 @@ static void write_mv vp8_encode_motion_vector(w, &e, mvc); } -static void write_mb_features(vp8_writer *w, const MB_MODE_INFO *mi, const MACROBLOCKD *x) +// This function writes the current macro block's segnment id to the bitstream +// It should only be called if a segment map update is indicated. +static void write_mb_segid(vp8_writer *w, + const MB_MODE_INFO *mi, const MACROBLOCKD *x) { // Encode the MB segment id. if (x->segmentation_enabled && x->update_mb_segmentation_map) @@ -1033,9 +1036,7 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) update_mbintra_mode_probs(cpi); vp8_write_mvprobs(cpi); -#if CONFIG_SEGMENTATION - vp8_write_bit(w, (xd->temporal_update) ? 1:0); -#endif + while (++mb_row < pc->mb_rows) { int mb_col = -1; @@ -1090,18 +1091,18 @@ static void pack_inter_mode_mvs(VP8_COMP *const cpi) { vp8_write(w,1,xd->mb_segment_tree_probs[3+sum]); segment_cost += vp8_cost_one(xd->mb_segment_tree_probs[3+sum]); - write_mb_features(w, mi, &cpi->mb.e_mbd); + write_mb_segid(w, mi, &cpi->mb.e_mbd); cpi->segmentation_map[index] = segment_id; } } else { - write_mb_features(w, mi, &cpi->mb.e_mbd); + write_mb_segid(w, mi, &cpi->mb.e_mbd); cpi->segmentation_map[index] = segment_id; } index++; #else - write_mb_features(w, mi, &cpi->mb.e_mbd); + write_mb_segid(w, mi, &cpi->mb.e_mbd); #endif } @@ -1309,11 +1310,11 @@ static void write_kfmodes(VP8_COMP *cpi) { #if CONFIG_SEGMENTATION - write_mb_features(bc, &m->mbmi, &cpi->mb.e_mbd); + write_mb_segid(bc, &m->mbmi, &cpi->mb.e_mbd); cpi->segmentation_map[index] = segment_id; index++; #else - write_mb_features(bc, &m->mbmi, &cpi->mb.e_mbd); + write_mb_segid(bc, &m->mbmi, &cpi->mb.e_mbd); #endif } @@ -2020,8 +2021,13 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size) // Indicate which features are enabled if (xd->segmentation_enabled) { - // Signal whether or not the segmentation map is being updated. + // Indicate whether or not the segmentation map is being updated. vp8_write_bit(bc, (xd->update_mb_segmentation_map) ? 1 : 0); +#if CONFIG_SEGMENTATION + // If it is, then indicate the method that will be used. + if ( xd->update_mb_segmentation_map ) + vp8_write_bit(bc, (xd->temporal_update) ? 1:0); +#endif vp8_write_bit(bc, (xd->update_mb_segmentation_data) ? 1 : 0); if (xd->update_mb_segmentation_data) diff --git a/vp8/encoder/encodeframe.c b/vp8/encoder/encodeframe.c index b24b39633..28ef7c6b9 100644 --- a/vp8/encoder/encodeframe.c +++ b/vp8/encoder/encodeframe.c @@ -42,12 +42,6 @@ #define IF_RTCD(x) NULL #endif -#if CONFIG_SEGMENTATION -#define SEEK_SEGID 12 -#define SEEK_SAMEID 4 -#define SEEK_DIFFID 7 -#endif - #ifdef ENC_DEBUG int enc_debug=0; int mb_row_debug, mb_col_debug; @@ -955,8 +949,6 @@ void vp8_encode_frame(VP8_COMP *cpi) #if CONFIG_SEGMENTATION int segment_counts[MAX_MB_SEGMENTS + SEEK_SEGID]; - int prob[3]; - int new_cost, original_cost; #else int segment_counts[MAX_MB_SEGMENTS]; #endif @@ -1098,14 +1090,10 @@ void vp8_encode_frame(VP8_COMP *cpi) { int i, j; - if (xd->segmentation_enabled) + for (i = 0; i < cpi->encoding_thread_count; i++) { - - for (i = 0; i < cpi->encoding_thread_count; i++) - { - for (j = 0; j < 4; j++) - segment_counts[j] += cpi->mb_row_ei[i].segment_counts[j]; - } + for (j = 0; j < 4; j++) + segment_counts[j] += cpi->mb_row_ei[i].segment_counts[j]; } } @@ -1150,92 +1138,10 @@ void vp8_encode_frame(VP8_COMP *cpi) // Set to defaults vpx_memset(xd->mb_segment_tree_probs, 255 , sizeof(xd->mb_segment_tree_probs)); -#if CONFIG_SEGMENTATION - - tot_count = segment_counts[12] + segment_counts[13] + segment_counts[14] + segment_counts[15]; - count1 = segment_counts[12] + segment_counts[13]; - count2 = segment_counts[14] + segment_counts[15]; - - if (tot_count) - prob[0] = (count1 * 255) / tot_count; - - if (count1 > 0) - prob[1] = (segment_counts[12] * 255) /count1; - - if (count2 > 0) - prob[2] = (segment_counts[14] * 255) /count2; - - if (cm->frame_type != KEY_FRAME) - { - tot_count = segment_counts[4] + segment_counts[7]; - if (tot_count) - xd->mb_segment_tree_probs[3] = (segment_counts[4] * 255)/tot_count; - - tot_count = segment_counts[5] + segment_counts[8]; - if (tot_count) - xd->mb_segment_tree_probs[4] = (segment_counts[5] * 255)/tot_count; - - tot_count = segment_counts[6] + segment_counts[9]; - if (tot_count) - xd->mb_segment_tree_probs[5] = (segment_counts[6] * 255)/tot_count; - } - - tot_count = segment_counts[0] + segment_counts[1] + segment_counts[2] + segment_counts[3]; - count3 = segment_counts[0] + segment_counts[1]; - count4 = segment_counts[2] + segment_counts[3]; - - if (tot_count) - xd->mb_segment_tree_probs[0] = (count3 * 255) / tot_count; - if (count3 > 0) - xd->mb_segment_tree_probs[1] = (segment_counts[0] * 255) /count3; - - if (count4 > 0) - xd->mb_segment_tree_probs[2] = (segment_counts[2] * 255) /count4; - - for (i = 0; i < MB_FEATURE_TREE_PROBS+3; i++) - { - if (xd->mb_segment_tree_probs[i] == 0) - xd->mb_segment_tree_probs[i] = 1; - } - - original_cost = count1 * vp8_cost_zero(prob[0]) + count2 * vp8_cost_one(prob[0]); - - if (count1 > 0) - original_cost += segment_counts[12] * vp8_cost_zero(prob[1]) + segment_counts[13] * vp8_cost_one(prob[1]); - - if (count2 > 0) - original_cost += segment_counts[14] * vp8_cost_zero(prob[2]) + segment_counts[15] * vp8_cost_one(prob[2]) ; - - new_cost = 0; - - if (cm->frame_type != KEY_FRAME) - { - new_cost = segment_counts[4] * vp8_cost_zero(xd->mb_segment_tree_probs[3]) + segment_counts[7] * vp8_cost_one(xd->mb_segment_tree_probs[3]); - - new_cost += segment_counts[5] * vp8_cost_zero(xd->mb_segment_tree_probs[4]) + segment_counts[8] * vp8_cost_one(xd->mb_segment_tree_probs[4]); - - new_cost += segment_counts[6] * vp8_cost_zero(xd->mb_segment_tree_probs[5]) + segment_counts[9] * vp8_cost_one (xd->mb_segment_tree_probs[5]); - } - - if (tot_count > 0) - new_cost += count3 * vp8_cost_zero(xd->mb_segment_tree_probs[0]) + count4 * vp8_cost_one(xd->mb_segment_tree_probs[0]); - - if (count3 > 0) - new_cost += segment_counts[0] * vp8_cost_zero(xd->mb_segment_tree_probs[1]) + segment_counts[1] * vp8_cost_one(xd->mb_segment_tree_probs[1]); - - if (count4 > 0) - new_cost += segment_counts[2] * vp8_cost_zero(xd->mb_segment_tree_probs[2]) + segment_counts[3] * vp8_cost_one(xd->mb_segment_tree_probs[2]) ; - - if (new_cost < original_cost) - xd->temporal_update = 1; - else - { - xd->temporal_update = 0; - xd->mb_segment_tree_probs[0] = prob[0]; - xd->mb_segment_tree_probs[1] = prob[1]; - xd->mb_segment_tree_probs[2] = prob[2]; - } +#if CONFIG_SEGMENTATION + // Select the coding strategy for the segment map (temporal or spatial) + choose_segmap_coding_method( cpi, segment_counts ); #else tot_count = segment_counts[0] + segment_counts[1] + segment_counts[2] + segment_counts[3]; count1 = segment_counts[0] + segment_counts[1]; diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h index f2bff98c5..817aaafea 100644 --- a/vp8/encoder/onyx_int.h +++ b/vp8/encoder/onyx_int.h @@ -56,6 +56,12 @@ #define VP8_TEMPORAL_ALT_REF 1 #endif +#if CONFIG_SEGMENTATION +#define SEEK_SEGID 12 +#define SEEK_SAMEID 4 +#define SEEK_DIFFID 7 +#endif + typedef struct { int kf_indicated; diff --git a/vp8/encoder/segmentation.c b/vp8/encoder/segmentation.c index 752053dd9..ac8611ef6 100644 --- a/vp8/encoder/segmentation.c +++ b/vp8/encoder/segmentation.c @@ -114,3 +114,129 @@ void vp8_set_segment_data(VP8_PTR ptr, // vpx_memcpy(cpi->mb.e_mbd.segment_feature_mask, 0, // sizeof(cpi->mb.e_mbd.segment_feature_mask)); } + +#if CONFIG_SEGMENTATION +void choose_segmap_coding_method( VP8_COMP *cpi, + int * segment_counts ) +{ + VP8_COMMON *const cm = & cpi->common; + MACROBLOCKD *const xd = & cpi->mb.e_mbd; + + int tot_count; + int i; + int count1,count2,count3,count4; + int prob[3]; + int new_cost, original_cost; + + // Select the coding strategy for the segment map (temporal or spatial) + tot_count = segment_counts[12] + segment_counts[13] + + segment_counts[14] + segment_counts[15]; + count1 = segment_counts[12] + segment_counts[13]; + count2 = segment_counts[14] + segment_counts[15]; + + if (tot_count) + prob[0] = (count1 * 255) / tot_count; + + if (count1 > 0) + prob[1] = (segment_counts[12] * 255) /count1; + + if (count2 > 0) + prob[2] = (segment_counts[14] * 255) /count2; + + if (cm->frame_type != KEY_FRAME) + { + tot_count = segment_counts[4] + segment_counts[7]; + if (tot_count) + xd->mb_segment_tree_probs[3] = (segment_counts[4] * 255)/tot_count; + + tot_count = segment_counts[5] + segment_counts[8]; + if (tot_count) + xd->mb_segment_tree_probs[4] = (segment_counts[5] * 255)/tot_count; + + tot_count = segment_counts[6] + segment_counts[9]; + if (tot_count) + xd->mb_segment_tree_probs[5] = (segment_counts[6] * 255)/tot_count; + } + + tot_count = segment_counts[0] + segment_counts[1] + + segment_counts[2] + segment_counts[3]; + count3 = segment_counts[0] + segment_counts[1]; + count4 = segment_counts[2] + segment_counts[3]; + + if (tot_count) + xd->mb_segment_tree_probs[0] = (count3 * 255) / tot_count; + + if (count3 > 0) + xd->mb_segment_tree_probs[1] = (segment_counts[0] * 255) /count3; + + if (count4 > 0) + xd->mb_segment_tree_probs[2] = (segment_counts[2] * 255) /count4; + + for (i = 0; i < MB_FEATURE_TREE_PROBS+3; i++) + { + if (xd->mb_segment_tree_probs[i] == 0) + xd->mb_segment_tree_probs[i] = 1; + } + + original_cost = count1 * vp8_cost_zero(prob[0]) + + count2 * vp8_cost_one(prob[0]); + + if (count1 > 0) + original_cost += segment_counts[12] * vp8_cost_zero(prob[1]) + + segment_counts[13] * vp8_cost_one(prob[1]); + + if (count2 > 0) + original_cost += segment_counts[14] * vp8_cost_zero(prob[2]) + + segment_counts[15] * vp8_cost_one(prob[2]) ; + + new_cost = 0; + + if (cm->frame_type != KEY_FRAME) + { + new_cost = segment_counts[4] * + vp8_cost_zero(xd->mb_segment_tree_probs[3]) + + segment_counts[7] * + vp8_cost_one(xd->mb_segment_tree_probs[3]); + + new_cost += segment_counts[5] * + vp8_cost_zero(xd->mb_segment_tree_probs[4]) + + segment_counts[8] * + vp8_cost_one(xd->mb_segment_tree_probs[4]); + + new_cost += segment_counts[6] * + vp8_cost_zero(xd->mb_segment_tree_probs[5]) + + segment_counts[9] * + vp8_cost_one (xd->mb_segment_tree_probs[5]); + } + + if (tot_count > 0) + new_cost += count3 * vp8_cost_zero(xd->mb_segment_tree_probs[0]) + + count4 * vp8_cost_one(xd->mb_segment_tree_probs[0]); + + if (count3 > 0) + new_cost += segment_counts[0] * + vp8_cost_zero(xd->mb_segment_tree_probs[1]) + + segment_counts[1] * + vp8_cost_one(xd->mb_segment_tree_probs[1]); + + if (count4 > 0) + new_cost += segment_counts[2] * + vp8_cost_zero(xd->mb_segment_tree_probs[2]) + + segment_counts[3] * + vp8_cost_one(xd->mb_segment_tree_probs[2]) ; + + if (new_cost < original_cost) + xd->temporal_update = 1; + else + { + xd->temporal_update = 0; + xd->mb_segment_tree_probs[0] = prob[0]; + xd->mb_segment_tree_probs[1] = prob[1]; + xd->mb_segment_tree_probs[2] = prob[2]; + } + + // ***** TODO + // PGW temp test code fix value as spatial + xd->temporal_update = 0; +} +#endif diff --git a/vp8/encoder/segmentation.h b/vp8/encoder/segmentation.h index 6c1683c17..b6394fd09 100644 --- a/vp8/encoder/segmentation.h +++ b/vp8/encoder/segmentation.h @@ -38,4 +38,9 @@ extern void vp8_set_segmentation_map(VP8_PTR ptr, unsigned char *segmentation_ma // extern void vp8_set_segment_data(VP8_PTR ptr, signed char *feature_data, unsigned char abs_delta); +#if CONFIG_SEGMENTATION +extern void choose_segmap_coding_method( VP8_COMP *cpi, + int * segment_counts ); +#endif + #endif /* __INC_SEGMENTATION_H__ */ -- cgit v1.2.3