diff --git a/configure b/configure index 311f86e9c017c6d81510fc3a194e8f2ba6e4ab21..8dc8900eec3b9261768fb981c782c7c76497d89d 100755 --- a/configure +++ b/configure @@ -227,6 +227,7 @@ EXPERIMENT_LIST=" newlpf enhanced_interp superblocks + feature_updates " CONFIG_LIST=" external_build diff --git a/vp8/common/blockd.h b/vp8/common/blockd.h index f6ff1c2a8d3eca9904be6a4b01ad18c75ca66d67..cadc442297b367e8ea823a2f3051cfef250c01ab 100644 --- a/vp8/common/blockd.h +++ b/vp8/common/blockd.h @@ -279,6 +279,12 @@ typedef struct MacroBlockD signed char segment_feature_data[MAX_MB_SEGMENTS][SEG_LVL_MAX]; unsigned int segment_feature_mask[MAX_MB_SEGMENTS]; +#if CONFIG_FEATUREUPDATES + // keep around the last set so we can figure out what updates... + unsigned int old_segment_feature_mask[MAX_MB_SEGMENTS]; + signed char old_segment_feature_data[MAX_MB_SEGMENTS][SEG_LVL_MAX]; +#endif + /* mode_based Loop filter adjustment */ unsigned char mode_ref_lf_delta_enabled; unsigned char mode_ref_lf_delta_update; diff --git a/vp8/common/seg_common.c b/vp8/common/seg_common.c index 44588aa9620e149ebb888839778ad50e7ea723e9..3ba374a4952c045cb1a9ffc93988b39fdd4c82cd 100644 --- a/vp8/common/seg_common.c +++ b/vp8/common/seg_common.c @@ -80,7 +80,56 @@ int get_segdata( MACROBLOCKD *xd, { return xd->segment_feature_data[segment_id][feature_id]; } +#if CONFIG_FEATUREUPDATES +int old_segfeature_active( MACROBLOCKD *xd, + int segment_id, + SEG_LVL_FEATURES feature_id ) +{ + // Return true if mask bit set and segmentation enabled. + return ( xd->segmentation_enabled && + ( xd->old_segment_feature_mask[segment_id] & + (0x01 << feature_id) ) ); +} + +int get_old_segdata( MACROBLOCKD *xd, + int segment_id, + SEG_LVL_FEATURES feature_id ) +{ + return xd->old_segment_feature_data[segment_id][feature_id]; +} +int segfeature_changed( MACROBLOCKD *xd, + int segment_id, + SEG_LVL_FEATURES feature_id ) +{ + // Return true if mask bit or data is different from last time + return + ( xd->segmentation_enabled && + ( + (xd->old_segment_feature_mask[segment_id] & (1 << feature_id) ) != + (xd->segment_feature_mask[segment_id] & (1 << feature_id) ) + || xd->old_segment_feature_data[segment_id][feature_id] != + xd->segment_feature_data[segment_id][feature_id] + ) + ); +} + +void save_segment_info ( MACROBLOCKD *xd ) +{ + int i,j; + for (i = 0; i < MAX_MB_SEGMENTS; i++) + { + xd->old_segment_feature_mask[i] = xd->segment_feature_mask[i]; + + // For each segmentation codable feature... + for (j = 0; j < SEG_LVL_MAX; j++) + { + xd->old_segment_feature_data[i][j]=xd->segment_feature_data[i][j]; + + } + } +} +#endif void clear_segref( MACROBLOCKD *xd, int segment_id ) { xd->segment_feature_data[segment_id][SEG_LVL_REF_FRAME] = 0; diff --git a/vp8/common/seg_common.h b/vp8/common/seg_common.h index f3f2d9f1983ed4b74f7ad2ffc1b40c28fe23d97d..bfd364e6d80d3562d7caef6409134cb8689e30c3 100644 --- a/vp8/common/seg_common.h +++ b/vp8/common/seg_common.h @@ -46,6 +46,27 @@ int get_segdata( MACROBLOCKD *xd, int segment_id, SEG_LVL_FEATURES feature_id ); +#if CONFIG_FEATUREUPDATES + +int old_segfeature_active( MACROBLOCKD *xd, + int segment_id, + SEG_LVL_FEATURES feature_id ); + +int get_old_segdata( MACROBLOCKD *xd, + int segment_id, + SEG_LVL_FEATURES feature_id ); + +void save_segment_info ( MACROBLOCKD *xd ); + +int segfeature_changed( MACROBLOCKD *xd, + int segment_id, + SEG_LVL_FEATURES feature_id ); + + + +#endif + + void clear_segref( MACROBLOCKD *xd, int segment_id ); void set_segref( MACROBLOCKD *xd, diff --git a/vp8/decoder/decodframe.c b/vp8/decoder/decodframe.c index c5385a022c02d1b667eefeeff23102b6eca64dd7..abf85eb28e955b9324e2473fa55c0b28e428f977 100644 --- a/vp8/decoder/decodframe.c +++ b/vp8/decoder/decodframe.c @@ -1158,6 +1158,39 @@ int vp8_decode_frame(VP8D_COMP *pbi) // For each of the segments features... for (j = 0; j < SEG_LVL_MAX; j++) { + +#if CONFIG_FEATUREUPDATES + // feature updated? + if (vp8_read_bit(bc)) + { + int active=1; + + if ( segfeature_active( xd, i, j )) + active=vp8_read_bit(bc); + + // Is the feature enabled + if (active) + { + // Update the feature data and mask + enable_segfeature(xd, i, j); + + data = (signed char)vp8_read_literal( + bc, seg_feature_data_bits(j)); + + // Is the segment data signed.. + if ( is_segfeature_signed(j) ) + { + if (vp8_read_bit(bc)) + data = - data; + } + } + else + data = 0; + + set_segdata(xd, i, j, data); + } + +#else // Is the feature enabled if (vp8_read_bit(bc)) { @@ -1178,6 +1211,7 @@ int vp8_decode_frame(VP8D_COMP *pbi) data = 0; set_segdata(xd, i, j, data); +#endif } } } diff --git a/vp8/encoder/bitstream.c b/vp8/encoder/bitstream.c index 2eb959d795bd8e694e3199154f0886a047bc6f3b..078a297914439c7ad799acce360585cb0857e890 100644 --- a/vp8/encoder/bitstream.c +++ b/vp8/encoder/bitstream.c @@ -2662,7 +2662,7 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size) vp8_write_bit(bc, (xd->segmentation_enabled) ? 1 : 0); // Indicate which features are enabled - if (xd->segmentation_enabled) + if ( xd->segmentation_enabled ) { // Indicate whether or not the segmentation map is being updated. vp8_write_bit(bc, (xd->update_mb_segmentation_map) ? 1 : 0); @@ -2689,6 +2689,58 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size) { Data = get_segdata( xd, i, j ); + +#if CONFIG_FEATUREUPDATES + + // check if there's an update + if(segfeature_changed( xd,i,j) ) + { + vp8_write_bit(bc, 1); + + if ( segfeature_active( xd, i, j ) ) + { + // this bit is to say we are still + // active/ if we were inactive + // this is unnecessary + if ( old_segfeature_active( xd, i, j )) + { + vp8_write_bit(bc, 1); + } + // Is the segment data signed.. + if ( is_segfeature_signed(j) ) + { + // Encode the relevant feature data + if (Data < 0) + { + Data = - Data; + vp8_write_literal(bc, Data, + seg_feature_data_bits(j)); + vp8_write_bit(bc, 1); + } + else + { + vp8_write_literal(bc, Data, + seg_feature_data_bits(j)); + vp8_write_bit(bc, 0); + } + } + // Unsigned data element so no sign bit needed + else + vp8_write_literal(bc, Data, + seg_feature_data_bits(j)); + } + // feature is inactive now + else if ( old_segfeature_active( xd, i, j )) + { + vp8_write_bit(bc, 0); + } + } + else + { + vp8_write_bit(bc,0); + } +#else + // If the feature is enabled... if ( segfeature_active( xd, i, j ) ) { @@ -2702,27 +2754,33 @@ void vp8_pack_bitstream(VP8_COMP *cpi, unsigned char *dest, unsigned long *size) { Data = - Data; vp8_write_literal(bc, Data, - seg_feature_data_bits(j)); + seg_feature_data_bits(j)); vp8_write_bit(bc, 1); } else { vp8_write_literal(bc, Data, - seg_feature_data_bits(j)); + seg_feature_data_bits(j)); vp8_write_bit(bc, 0); } } // Unsigned data element so no sign bit needed else vp8_write_literal(bc, Data, - seg_feature_data_bits(j)); + seg_feature_data_bits(j)); } else vp8_write_bit(bc, 0); +#endif } } } +#if CONFIG_FEATUREUPDATES + // save the segment info for updates next frame + save_segment_info ( xd ); +#endif + if (xd->update_mb_segmentation_map) { // Send the tree probabilities used to decode unpredicted