From 27bb4777cd8ecf0a0fa2599a25c84a13c6789d9b Mon Sep 17 00:00:00 2001 From: Paul Wilkins Date: Tue, 23 Apr 2013 14:01:55 +0100 Subject: [PATCH] Simple implicit segmentation experiment. Change-Id: Iaef16122732c2a81e0927f9862b51b68dc788712 --- vp9/common/vp9_blockd.h | 6 +++- vp9/common/vp9_seg_common.c | 22 +++++++++++++ vp9/common/vp9_seg_common.h | 4 +++ vp9/decoder/vp9_decodframe.c | 13 ++++++++ vp9/encoder/vp9_bitstream.c | 3 ++ vp9/encoder/vp9_onyx_if.c | 78 ++++++++++++++++++++++++++++++++++++++++++-- 6 files changed, 122 insertions(+), 4 deletions(-) diff --git a/vp9/common/vp9_blockd.h b/vp9/common/vp9_blockd.h index e790468..fcc5c4e 100644 --- a/vp9/common/vp9_blockd.h +++ b/vp9/common/vp9_blockd.h @@ -268,7 +268,7 @@ typedef struct { unsigned char mb_skip_coeff; /* does this mb has coefficients at all, 1=no coefficients, 0=need decode tokens */ unsigned char need_to_clamp_mvs; unsigned char need_to_clamp_secondmv; - unsigned char segment_id; /* Which set of segmentation parameters should be used for this MB */ + unsigned char segment_id; // Segment id for current frame // Flags used for prediction status of various bistream signals unsigned char seg_id_predicted; @@ -384,6 +384,10 @@ typedef struct macroblockd { /* 0 (do not update) 1 (update) the macroblock segmentation map. */ unsigned char update_mb_segmentation_map; +#if CONFIG_IMPLICIT_SEGMENTATION + unsigned char allow_implicit_segment_update; +#endif + /* 0 (do not update) 1 (update) the macroblock segmentation feature data. */ unsigned char update_mb_segmentation_data; diff --git a/vp9/common/vp9_seg_common.c b/vp9/common/vp9_seg_common.c index df67cff..4c913e2 100644 --- a/vp9/common/vp9_seg_common.c +++ b/vp9/common/vp9_seg_common.c @@ -85,4 +85,26 @@ int vp9_check_segref(const MACROBLOCKD *xd, int segment_id, (1 << ref_frame)) ? 1 : 0; } + +#if CONFIG_IMPLICIT_SEGMENTATION +// This function defines an implicit segmentation for the next frame based +// on predcition and transform decisions in the current frame. +// For test purposes at the moment only TX size is used. +void vp9_implicit_segment_map_update(VP9_COMMON * cm) { + int row, col; + MODE_INFO *mi, *mi_ptr = cm->mi; + unsigned char * map_ptr = cm->last_frame_seg_map; + + for (row = 0; row < cm->mb_rows; row++) { + mi = mi_ptr; + // Experimental use of tx size to define implicit segmentation + for (col = 0; col < cm->mb_cols; ++col, ++mi) { + map_ptr[col] = mi->mbmi.txfm_size; + } + mi_ptr += cm->mode_info_stride; + map_ptr += cm->mb_cols; + } +} +#endif + // TBD? Functions to read and write segment data with range / validity checking diff --git a/vp9/common/vp9_seg_common.h b/vp9/common/vp9_seg_common.h index 243ff88..4550dd1 100644 --- a/vp9/common/vp9_seg_common.h +++ b/vp9/common/vp9_seg_common.h @@ -55,5 +55,9 @@ int vp9_check_segref(const MACROBLOCKD *xd, int segment_id, MV_REFERENCE_FRAME ref_frame); +#if CONFIG_IMPLICIT_SEGMENTATION +void vp9_implicit_segment_map_update(VP9_COMMON * cm); +#endif + #endif // VP9_COMMON_VP9_SEG_COMMON_H_ diff --git a/vp9/decoder/vp9_decodframe.c b/vp9/decoder/vp9_decodframe.c index bc820cd..9970258 100644 --- a/vp9/decoder/vp9_decodframe.c +++ b/vp9/decoder/vp9_decodframe.c @@ -1093,6 +1093,9 @@ static void setup_segmentation(VP9_COMMON *pc, MACROBLOCKD *xd, vp9_reader *r) { xd->update_mb_segmentation_map = 0; xd->update_mb_segmentation_data = 0; +#if CONFIG_IMPLICIT_SEGMENTATION + xd->allow_implicit_segment_update = 0; +#endif xd->segmentation_enabled = vp9_read_bit(r); if (!xd->segmentation_enabled) @@ -1100,6 +1103,9 @@ static void setup_segmentation(VP9_COMMON *pc, MACROBLOCKD *xd, vp9_reader *r) { // Segmentation map update xd->update_mb_segmentation_map = vp9_read_bit(r); +#if CONFIG_IMPLICIT_SEGMENTATION + xd->allow_implicit_segment_update = vp9_read_bit(r); +#endif if (xd->update_mb_segmentation_map) { for (i = 0; i < MB_FEATURE_TREE_PROBS; i++) xd->mb_segment_tree_probs[i] = vp9_read_bit(r) ? vp9_read_prob(r) @@ -1628,6 +1634,13 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) { } } +#if CONFIG_IMPLICIT_SEGMENTATION + // If signalled at the frame level apply implicit updates to the segment map. + if (!pc->error_resilient_mode && xd->allow_implicit_segment_update) { + vp9_implicit_segment_map_update(pc); + } +#endif + if (pc->refresh_entropy_probs) { vpx_memcpy(&pc->frame_contexts[pc->frame_context_idx], &pc->fc, sizeof(pc->fc)); diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c index 2231621..b65e8a0 100644 --- a/vp9/encoder/vp9_bitstream.c +++ b/vp9/encoder/vp9_bitstream.c @@ -1989,6 +1989,9 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest, if (xd->segmentation_enabled) { // Indicate whether or not the segmentation map is being updated. vp9_write_bit(&header_bc, (xd->update_mb_segmentation_map) ? 1 : 0); +#if CONFIG_IMPLICIT_SEGMENTATION + vp9_write_bit(&header_bc, (xd->allow_implicit_segment_update) ? 1 : 0); +#endif // If it is, then indicate the method that will be used. if (xd->update_mb_segmentation_map) { diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index b294870..03a8388 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -285,6 +285,9 @@ static void setup_features(VP9_COMP *cpi) { xd->update_mb_segmentation_map = 0; xd->update_mb_segmentation_data = 0; +#if CONFIG_IMPLICIT_SEGMENTATION + xd->allow_implicit_segment_update = 0; +#endif vpx_memset(xd->mb_segment_tree_probs, 255, sizeof(xd->mb_segment_tree_probs)); vp9_clearall_segfeatures(xd); @@ -389,6 +392,9 @@ static void configure_static_seg_features(VP9_COMP *cpi) { vpx_memset(cpi->segmentation_map, 0, (cm->mb_rows * cm->mb_cols)); xd->update_mb_segmentation_map = 0; xd->update_mb_segmentation_data = 0; +#if CONFIG_IMPLICIT_SEGMENTATION + xd->allow_implicit_segment_update = 0; +#endif cpi->static_mb_pct = 0; // Disable segmentation @@ -402,6 +408,9 @@ static void configure_static_seg_features(VP9_COMP *cpi) { vpx_memset(cpi->segmentation_map, 0, (cm->mb_rows * cm->mb_cols)); xd->update_mb_segmentation_map = 0; xd->update_mb_segmentation_data = 0; +#if CONFIG_IMPLICIT_SEGMENTATION + xd->allow_implicit_segment_update = 0; +#endif cpi->static_mb_pct = 0; // Disable segmentation and individual segment features by default @@ -502,6 +511,45 @@ static void configure_static_seg_features(VP9_COMP *cpi) { } } +#if CONFIG_IMPLICIT_SEGMENTATION +static void configure_implicit_segmentation(VP9_COMP *cpi) { + VP9_COMMON *cm = &cpi->common; + MACROBLOCKD *xd = &cpi->mb.e_mbd; + int i; + int qi_delta; + double q_target = cpi->active_worst_quality * 1.10; + + // Set the flags to allow implicit segment update but disallow explicit update + xd->segmentation_enabled = 1; + xd->allow_implicit_segment_update = 1; + xd->update_mb_segmentation_map = 0; + + // For key frames clear down the segment map to a default state. + if (cm->frame_type == KEY_FRAME) { + // Clear down the global segmentation map + vpx_memset(cpi->segmentation_map, 0, (cm->mb_rows * cm->mb_cols)); + + // Clear down the segment features. + vp9_clearall_segfeatures(xd); + + xd->update_mb_segmentation_data = 1; + + // Enable use of q deltas on segments + for (i = 0; i < MAX_MB_SEGMENTS; ++i) { + qi_delta = compute_qdelta(cpi, cpi->active_worst_quality, q_target); + vp9_set_segdata(xd, i, SEG_LVL_ALT_Q, qi_delta); + q_target *= 0.95; + vp9_enable_segfeature(xd, i, SEG_LVL_ALT_Q); + } + + // Where relevant assume segment data is delta data + xd->mb_segment_abs_delta = SEGMENT_DELTADATA; + } else { + xd->update_mb_segmentation_data = 0; + } +} +#endif + // DEBUG: Print out the segment id of each MB in the current frame. static void print_seg_map(VP9_COMP *cpi) { VP9_COMMON *cm = &cpi->common; @@ -739,8 +787,12 @@ void vp9_set_speed_features(VP9_COMP *cpi) { // Switch segmentation off. sf->static_segmentation = 0; #else +#if CONFIG_IMPLICIT_SEGMENTATION + sf->static_segmentation = 0; +#else sf->static_segmentation = 1; #endif +#endif sf->splitmode_breakout = 0; sf->mb16_breakout = 0; @@ -754,7 +806,11 @@ void vp9_set_speed_features(VP9_COMP *cpi) { // Switch segmentation off. sf->static_segmentation = 0; #else - sf->static_segmentation = 1; +#if CONFIG_IMPLICIT_SEGMENTATION + sf->static_segmentation = 0; +#else + sf->static_segmentation = 1; +#endif #endif sf->splitmode_breakout = 1; sf->mb16_breakout = 0; @@ -2716,7 +2772,8 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, } } - // Configure use of segmentation for enhanced coding of static regions. + // Configure experimental use of segmentation for enhanced coding of + // static regions if indicated. // Only allowed for now in second pass of two pass (as requires lagged coding) // and if the relevant speed feature flag is set. if ((cpi->pass == 2) && (cpi->sf.static_segmentation)) { @@ -3024,6 +3081,12 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, cpi->common.frame_context_idx = cpi->refresh_alt_ref_frame; vp9_setup_inter_frame(cpi); } + +#if CONFIG_IMPLICIT_SEGMENTATION + if (!cm->error_resilient_mode && !cpi->sf.static_segmentation) { + configure_implicit_segmentation(cpi); + } +#endif } // transform / motion compensation build reconstruction frame @@ -3288,8 +3351,17 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, cpi->dummy_packing = 0; vp9_pack_bitstream(cpi, dest, size); - if (cpi->mb.e_mbd.update_mb_segmentation_map) +#if CONFIG_IMPLICIT_SEGMENTATION + // Should we allow implicit update of the segment map. + if (xd->allow_implicit_segment_update && !cm->error_resilient_mode) { + vp9_implicit_segment_map_update(cm); + // or has there been an explicit update + } else if (xd->update_mb_segmentation_map) { +#else + if (xd->update_mb_segmentation_map) { +#endif update_reference_segmentation_map(cpi); + } release_scaled_references(cpi); update_reference_frames(cpi); -- 2.7.4