Simple implicit segmentation experiment.
authorPaul Wilkins <paulwilkins@google.com>
Tue, 23 Apr 2013 13:01:55 +0000 (14:01 +0100)
committerPaul Wilkins <paulwilkins@google.com>
Wed, 24 Apr 2013 09:04:27 +0000 (10:04 +0100)
Change-Id: Iaef16122732c2a81e0927f9862b51b68dc788712

vp9/common/vp9_blockd.h
vp9/common/vp9_seg_common.c
vp9/common/vp9_seg_common.h
vp9/decoder/vp9_decodframe.c
vp9/encoder/vp9_bitstream.c
vp9/encoder/vp9_onyx_if.c

index e790468..fcc5c4e 100644 (file)
@@ -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;
 
index df67cff..4c913e2 100644 (file)
@@ -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
index 243ff88..4550dd1 100644 (file)
@@ -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_
 
index bc820cd..9970258 100644 (file)
@@ -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));
index 2231621..b65e8a0 100644 (file)
@@ -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) {
index b294870..03a8388 100644 (file)
@@ -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);