Make update_map/temporal_update fields implicit for keyframes.
authorRonald S. Bultje <rsbultje@gmail.com>
Thu, 3 Sep 2015 20:08:29 +0000 (16:08 -0400)
committerRonald S. Bultje <rsbultje@gmail.com>
Fri, 4 Sep 2015 01:19:45 +0000 (21:19 -0400)
These frame types cannot make bitstream parsing depend on previous
frames, so the hypothetical combinations of e.g. keyframe=1 and
update_map=0 or keyframe=1 and temporal_update=1 are non-sensical.
Therefore, make it impossible to code such combinations in the vp10
bitstream header.

See issue 1044.

Change-Id: I3f0a83d5c7e3989541a469a909471424a285239d

vp10/decoder/decodeframe.c
vp10/decoder/decodemv.c
vp10/encoder/bitstream.c

index 518dec0..e3c97c6 100644 (file)
@@ -1012,8 +1012,9 @@ static void read_coef_probs(FRAME_CONTEXT *fc, TX_MODE tx_mode,
       read_coef_probs_common(fc->coef_probs[tx_size], r);
 }
 
-static void setup_segmentation(struct segmentation *seg,
+static void setup_segmentation(VP10_COMMON *const cm,
                                struct vpx_read_bit_buffer *rb) {
+  struct segmentation *const seg = &cm->seg;
   int i, j;
 
   seg->update_map = 0;
@@ -1024,13 +1025,21 @@ static void setup_segmentation(struct segmentation *seg,
     return;
 
   // Segmentation map update
-  seg->update_map = vpx_rb_read_bit(rb);
+  if (frame_is_intra_only(cm) || cm->error_resilient_mode) {
+    seg->update_map = 1;
+  } else {
+    seg->update_map = vpx_rb_read_bit(rb);
+  }
   if (seg->update_map) {
     for (i = 0; i < SEG_TREE_PROBS; i++)
       seg->tree_probs[i] = vpx_rb_read_bit(rb) ? vpx_rb_read_literal(rb, 8)
                                                : MAX_PROB;
 
-    seg->temporal_update = vpx_rb_read_bit(rb);
+    if (frame_is_intra_only(cm) || cm->error_resilient_mode) {
+      seg->temporal_update = 0;
+    } else {
+      seg->temporal_update = vpx_rb_read_bit(rb);
+    }
     if (seg->temporal_update) {
       for (i = 0; i < PREDICTION_PROBS; i++)
         seg->pred_probs[i] = vpx_rb_read_bit(rb) ? vpx_rb_read_literal(rb, 8)
@@ -1953,7 +1962,7 @@ static size_t read_uncompressed_header(VP10Decoder *pbi,
 
   setup_loopfilter(&cm->lf, rb);
   setup_quantization(cm, &pbi->mb, rb);
-  setup_segmentation(&cm->seg, rb);
+  setup_segmentation(cm, rb);
   setup_segmentation_dequant(cm);
 
   setup_tile_info(cm, rb);
index 681e02f..b190f73 100644 (file)
@@ -116,18 +116,6 @@ static void set_segment_id(VP10_COMMON *cm, int mi_offset,
       cm->current_frame_seg_map[mi_offset + y * cm->mi_cols + x] = segment_id;
 }
 
-static void copy_segment_id(const VP10_COMMON *cm,
-                           const uint8_t *last_segment_ids,
-                           uint8_t *current_segment_ids,
-                           int mi_offset, int x_mis, int y_mis) {
-  int x, y;
-
-  for (y = 0; y < y_mis; y++)
-    for (x = 0; x < x_mis; x++)
-      current_segment_ids[mi_offset + y * cm->mi_cols + x] =  last_segment_ids ?
-          last_segment_ids[mi_offset + y * cm->mi_cols + x] : 0;
-}
-
 static int read_intra_segment_id(VP10_COMMON *const cm, int mi_offset,
                                  int x_mis, int y_mis,
                                  vpx_reader *r) {
@@ -137,17 +125,25 @@ static int read_intra_segment_id(VP10_COMMON *const cm, int mi_offset,
   if (!seg->enabled)
     return 0;  // Default for disabled segmentation
 
-  if (!seg->update_map) {
-    copy_segment_id(cm, cm->last_frame_seg_map, cm->current_frame_seg_map,
-                    mi_offset, x_mis, y_mis);
-    return 0;
-  }
+  assert(seg->update_map && !seg->temporal_update);
 
   segment_id = read_segment_id(r, seg);
   set_segment_id(cm, mi_offset, x_mis, y_mis, segment_id);
   return segment_id;
 }
 
+static void copy_segment_id(const VP10_COMMON *cm,
+                           const uint8_t *last_segment_ids,
+                           uint8_t *current_segment_ids,
+                           int mi_offset, int x_mis, int y_mis) {
+  int x, y;
+
+  for (y = 0; y < y_mis; y++)
+    for (x = 0; x < x_mis; x++)
+      current_segment_ids[mi_offset + y * cm->mi_cols + x] =  last_segment_ids ?
+          last_segment_ids[mi_offset + y * cm->mi_cols + x] : 0;
+}
+
 static int read_inter_segment_id(VP10_COMMON *const cm, MACROBLOCKD *const xd,
                                  int mi_row, int mi_col, vpx_reader *r) {
   struct segmentation *const seg = &cm->seg;
index 356bc16..2b60ac5 100644 (file)
@@ -762,7 +762,11 @@ static void encode_segmentation(VP10_COMMON *cm, MACROBLOCKD *xd,
     return;
 
   // Segmentation map
-  vpx_wb_write_bit(wb, seg->update_map);
+  if (!frame_is_intra_only(cm) && !cm->error_resilient_mode) {
+    vpx_wb_write_bit(wb, seg->update_map);
+  } else {
+    assert(seg->update_map == 1);
+  }
   if (seg->update_map) {
     // Select the coding strategy (temporal or spatial)
     vp10_choose_segmap_coding_method(cm, xd);
@@ -776,7 +780,11 @@ static void encode_segmentation(VP10_COMMON *cm, MACROBLOCKD *xd,
     }
 
     // Write out the chosen coding method.
-    vpx_wb_write_bit(wb, seg->temporal_update);
+    if (!frame_is_intra_only(cm) && !cm->error_resilient_mode) {
+      vpx_wb_write_bit(wb, seg->temporal_update);
+    } else {
+      assert(seg->temporal_update == 0);
+    }
     if (seg->temporal_update) {
       for (i = 0; i < PREDICTION_PROBS; i++) {
         const int prob = seg->pred_probs[i];