ref: 27bb4777cd8ecf0a0fa2599a25c84a13c6789d9b
parent: 2a40085cb59dadfb58f8bd58dbfd7b79b174cd91
author: Paul Wilkins <paulwilkins@google.com>
date: Tue Apr 23 10:01:55 EDT 2013
Simple implicit segmentation experiment. Change-Id: Iaef16122732c2a81e0927f9862b51b68dc788712
--- a/vp9/common/vp9_blockd.h
+++ b/vp9/common/vp9_blockd.h
@@ -268,7 +268,7 @@
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;
@@ -383,6 +383,10 @@
/* 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;
--- a/vp9/common/vp9_seg_common.c
+++ b/vp9/common/vp9_seg_common.c
@@ -85,4 +85,26 @@
(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
--- a/vp9/common/vp9_seg_common.h
+++ b/vp9/common/vp9_seg_common.h
@@ -55,5 +55,9 @@
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_
--- a/vp9/decoder/vp9_decodframe.c
+++ b/vp9/decoder/vp9_decodframe.c
@@ -1093,6 +1093,9 @@
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 @@
// 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)
@@ -1627,6 +1633,13 @@
vp9_adapt_mode_context(pc);
}
}
+
+#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,
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -1989,6 +1989,9 @@
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) {
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -285,6 +285,9 @@
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 @@
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 @@
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 @@
}
}
+#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 @@
// 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,8 +806,12 @@
// 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 @@
}
}
- // 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 @@
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 @@
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);
--
⑨