shithub: libvpx

Download patch

ref: a23757633d456fe4b5018c1e68a6dc05619ef6f5
parent: 26e24b1dd73a53e46122093b151df7367aac72ce
author: Dmitry Kovalev <dkovalev@google.com>
date: Thu Jun 6 08:33:12 EDT 2013

Moving segmentation and tile info to uncompressed header.

Change-Id: I0ca77329d882a2026f6c1941b8e447d86bc87bda

--- a/vp9/decoder/vp9_decodframe.c
+++ b/vp9/decoder/vp9_decodframe.c
@@ -117,13 +117,8 @@
   return word;
 }
 
-static int decode_unsigned_max(vp9_reader *r, int max) {
-  int data = 0, bit = 0, lmax = max;
-
-  while (lmax) {
-    data |= vp9_read_bit(r) << bit++;
-    lmax >>= 1;
-  }
+static int decode_unsigned_max(struct vp9_read_bit_buffer *rb, int max) {
+  const int data = vp9_rb_read_literal(rb, get_unsigned_bits(max));
   return data > max ? max : data;
 }
 
@@ -566,53 +561,56 @@
 }
 
 static void read_coef_probs(VP9D_COMP *pbi, vp9_reader *r) {
-  const TXFM_MODE mode = pbi->common.txfm_mode;
+  const TXFM_MODE txfm_mode = pbi->common.txfm_mode;
   FRAME_CONTEXT *const fc = &pbi->common.fc;
 
   read_coef_probs_common(fc, TX_4X4, r);
 
-  if (mode > ONLY_4X4)
+  if (txfm_mode > ONLY_4X4)
     read_coef_probs_common(fc, TX_8X8, r);
 
-  if (mode > ALLOW_8X8)
+  if (txfm_mode > ALLOW_8X8)
     read_coef_probs_common(fc, TX_16X16, r);
 
-  if (mode > ALLOW_16X16)
+  if (txfm_mode > ALLOW_16X16)
     read_coef_probs_common(fc, TX_32X32, r);
 }
 
-static void setup_segmentation(VP9_COMMON *pc, MACROBLOCKD *xd, vp9_reader *r) {
+static void setup_segmentation(VP9D_COMP *pbi, struct vp9_read_bit_buffer *rb) {
   int i, j;
 
+  VP9_COMMON *const cm = &pbi->common;
+  MACROBLOCKD *const xd = &pbi->mb;
+
   xd->update_mb_segmentation_map = 0;
   xd->update_mb_segmentation_data = 0;
 
-  xd->segmentation_enabled = vp9_read_bit(r);
+  xd->segmentation_enabled = vp9_rb_read_bit(rb);
   if (!xd->segmentation_enabled)
     return;
 
   // Segmentation map update
-  xd->update_mb_segmentation_map = vp9_read_bit(r);
+  xd->update_mb_segmentation_map = vp9_rb_read_bit(rb);
   if (xd->update_mb_segmentation_map) {
     for (i = 0; i < MB_SEG_TREE_PROBS; i++)
-      xd->mb_segment_tree_probs[i] = vp9_read_bit(r) ? vp9_read_prob(r)
-                                                     : MAX_PROB;
+      xd->mb_segment_tree_probs[i] = vp9_rb_read_bit(rb) ?
+                                         vp9_rb_read_literal(rb, 8) : MAX_PROB;
 
-    pc->temporal_update = vp9_read_bit(r);
-    if (pc->temporal_update) {
+    cm->temporal_update = vp9_rb_read_bit(rb);
+    if (cm->temporal_update) {
       for (i = 0; i < PREDICTION_PROBS; i++)
-        pc->segment_pred_probs[i] = vp9_read_bit(r) ? vp9_read_prob(r)
-                                                    : MAX_PROB;
+        cm->segment_pred_probs[i] = vp9_rb_read_bit(rb) ?
+                                        vp9_rb_read_literal(rb, 8) : MAX_PROB;
     } else {
       for (i = 0; i < PREDICTION_PROBS; i++)
-        pc->segment_pred_probs[i] = MAX_PROB;
+        cm->segment_pred_probs[i] = MAX_PROB;
     }
   }
 
   // Segmentation data update
-  xd->update_mb_segmentation_data = vp9_read_bit(r);
+  xd->update_mb_segmentation_data = vp9_rb_read_bit(rb);
   if (xd->update_mb_segmentation_data) {
-    xd->mb_segment_abs_delta = vp9_read_bit(r);
+    xd->mb_segment_abs_delta = vp9_rb_read_bit(rb);
 
     vp9_clearall_segfeatures(xd);
 
@@ -619,12 +617,12 @@
     for (i = 0; i < MAX_MB_SEGMENTS; i++) {
       for (j = 0; j < SEG_LVL_MAX; j++) {
         int data = 0;
-        const int feature_enabled = vp9_read_bit(r);
+        const int feature_enabled = vp9_rb_read_bit(rb);
         if (feature_enabled) {
           vp9_enable_segfeature(xd, i, j);
-          data = decode_unsigned_max(r, vp9_seg_feature_data_max(j));
+          data = decode_unsigned_max(rb, vp9_seg_feature_data_max(j));
           if (vp9_is_segfeature_signed(j))
-            data = vp9_read_and_apply_sign(r, data);
+            data = vp9_rb_read_bit(rb) ? -data : data;
         }
         vp9_set_segdata(xd, i, j, data);
       }
@@ -676,8 +674,10 @@
 }
 
 static void setup_quantization(VP9D_COMP *pbi, struct vp9_read_bit_buffer *rb) {
+  MACROBLOCKD *const xd = &pbi->mb;
   VP9_COMMON *const cm = &pbi->common;
   int update = 0;
+
   cm->base_qindex = vp9_rb_read_literal(rb, QINDEX_BITS);
   update |= read_delta_q(rb, &cm->y_dc_delta_q);
   update |= read_delta_q(rb, &cm->uv_dc_delta_q);
@@ -684,6 +684,20 @@
   update |= read_delta_q(rb, &cm->uv_ac_delta_q);
   if (update)
     vp9_init_dequantizer(cm);
+
+  xd->lossless = cm->base_qindex == 0 &&
+                 cm->y_dc_delta_q == 0 &&
+                 cm->uv_dc_delta_q == 0 &&
+                 cm->uv_ac_delta_q == 0;
+  if (xd->lossless) {
+    xd->itxm_add          = vp9_idct_add_lossless_c;
+    xd->itxm_add_y_block  = vp9_idct_add_y_block_lossless_c;
+    xd->itxm_add_uv_block = vp9_idct_add_uv_block_lossless_c;
+  } else {
+    xd->itxm_add          = vp9_idct_add;
+    xd->itxm_add_y_block  = vp9_idct_add_y_block;
+    xd->itxm_add_uv_block = vp9_idct_add_uv_block;
+  }
 }
 
 static INTERPOLATIONFILTERTYPE read_interp_filter_type(
@@ -787,28 +801,34 @@
   }
 }
 
-static void decode_tiles(VP9D_COMP *pbi,
-                         const uint8_t *data, int first_partition_size,
-                         vp9_reader *header_bc, vp9_reader *residual_bc) {
-  VP9_COMMON *const pc = &pbi->common;
+static void setup_tile_info(VP9_COMMON *cm, struct vp9_read_bit_buffer *rb) {
+  int delta_log2_tiles;
 
-  const uint8_t *data_ptr = data + first_partition_size;
-  int tile_row, tile_col, delta_log2_tiles;
-
-  vp9_get_tile_n_bits(pc, &pc->log2_tile_columns, &delta_log2_tiles);
+  vp9_get_tile_n_bits(cm, &cm->log2_tile_columns, &delta_log2_tiles);
   while (delta_log2_tiles--) {
-    if (vp9_read_bit(header_bc)) {
-      pc->log2_tile_columns++;
+    if (vp9_rb_read_bit(rb)) {
+      cm->log2_tile_columns++;
     } else {
       break;
     }
   }
-  pc->log2_tile_rows = vp9_read_bit(header_bc);
-  if (pc->log2_tile_rows)
-    pc->log2_tile_rows += vp9_read_bit(header_bc);
-  pc->tile_columns = 1 << pc->log2_tile_columns;
-  pc->tile_rows    = 1 << pc->log2_tile_rows;
 
+  cm->log2_tile_rows = vp9_rb_read_bit(rb);
+  if (cm->log2_tile_rows)
+    cm->log2_tile_rows += vp9_rb_read_bit(rb);
+
+  cm->tile_columns = 1 << cm->log2_tile_columns;
+  cm->tile_rows    = 1 << cm->log2_tile_rows;
+}
+
+static void decode_tiles(VP9D_COMP *pbi,
+                         const uint8_t *data, size_t first_partition_size,
+                         vp9_reader *residual_bc) {
+  VP9_COMMON *const pc = &pbi->common;
+
+  const uint8_t *data_ptr = data + first_partition_size;
+  int tile_row, tile_col;
+
   // Note: this memset assumes above_context[0], [1] and [2]
   // are allocated as part of the same buffer.
   vpx_memset(pc->above_context[0], 0, sizeof(ENTROPY_CONTEXT) * 2 *
@@ -955,7 +975,10 @@
 
   setup_loopfilter(pbi, rb);
   setup_quantization(pbi, rb);
+  setup_segmentation(pbi, rb);
 
+  setup_tile_info(cm, rb);
+
   return vp9_rb_read_literal(rb, 16);
 }
 
@@ -999,27 +1022,11 @@
 
   mb_init_dequantizer(pc, &pbi->mb);  // MB level dequantizer setup
 
-  xd->lossless = pc->base_qindex == 0 &&
-                 pc->y_dc_delta_q == 0 &&
-                 pc->uv_dc_delta_q == 0 &&
-                 pc->uv_ac_delta_q == 0;
-  if (xd->lossless) {
-    xd->itxm_add          = vp9_idct_add_lossless_c;
-    xd->itxm_add_y_block  = vp9_idct_add_y_block_lossless_c;
-    xd->itxm_add_uv_block = vp9_idct_add_uv_block_lossless_c;
-  } else {
-    xd->itxm_add          = vp9_idct_add;
-    xd->itxm_add_y_block  = vp9_idct_add_y_block;
-    xd->itxm_add_uv_block = vp9_idct_add_uv_block;
-  }
-
   if (!keyframe)
     vp9_setup_interp_filters(xd, pc->mcomp_filter_type, pc);
 
   pc->fc = pc->frame_contexts[pc->frame_context_idx];
 
-  setup_segmentation(pc, xd, &header_bc);
-
   setup_txfm_mode(pc, xd->lossless, &header_bc);
 
   update_frame_context(&pc->fc);
@@ -1046,7 +1053,7 @@
 
   vp9_decode_mode_mvs_init(pbi, &header_bc);
 
-  decode_tiles(pbi, data, first_partition_size, &header_bc, &residual_bc);
+  decode_tiles(pbi, data, first_partition_size, &residual_bc);
 
   pc->last_width = pc->width;
   pc->last_height = pc->height;
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -60,15 +60,8 @@
   p[3] = value >> 24;
 }
 
-void vp9_encode_unsigned_max(vp9_writer *br, int data, int max) {
-  assert(data <= max);
-  while (max) {
-    vp9_write_bit(br, data & 1);
-    data >>= 1;
-    max >>= 1;
-  }
-}
 
+
 int recenter_nonneg(int v, int m) {
   if (v > (m << 1))
     return v;
@@ -88,6 +81,11 @@
   return cat;
 }
 
+void vp9_encode_unsigned_max(struct vp9_write_bit_buffer *wb,
+                             int data, int max) {
+  vp9_wb_write_literal(wb, data, get_unsigned_bits(max));
+}
+
 void encode_uniform(vp9_writer *w, int v, int n) {
   int l = get_unsigned_bits(n);
   int m;
@@ -1259,17 +1257,18 @@
 }
 
 
-static void encode_segmentation(VP9_COMP *cpi, vp9_writer *w) {
+static void encode_segmentation(VP9_COMP *cpi,
+                               struct vp9_write_bit_buffer *wb) {
   int i, j;
-  VP9_COMMON *const pc = &cpi->common;
+  VP9_COMMON *const cm = &cpi->common;
   MACROBLOCKD *const xd = &cpi->mb.e_mbd;
 
-  vp9_write_bit(w, xd->segmentation_enabled);
+  vp9_wb_write_bit(wb, xd->segmentation_enabled);
   if (!xd->segmentation_enabled)
     return;
 
   // Segmentation map
-  vp9_write_bit(w, xd->update_mb_segmentation_map);
+  vp9_wb_write_bit(wb, xd->update_mb_segmentation_map);
   if (xd->update_mb_segmentation_map) {
     // Select the coding strategy (temporal or spatial)
     vp9_choose_segmap_coding_method(cpi);
@@ -1276,56 +1275,45 @@
     // Write out probabilities used to decode unpredicted  macro-block segments
     for (i = 0; i < MB_SEG_TREE_PROBS; i++) {
       const int prob = xd->mb_segment_tree_probs[i];
-      if (prob != MAX_PROB) {
-        vp9_write_bit(w, 1);
-        vp9_write_prob(w, prob);
-      } else {
-        vp9_write_bit(w, 0);
-      }
+      const int update = prob != MAX_PROB;
+      vp9_wb_write_bit(wb, update);
+      if (update)
+        vp9_wb_write_literal(wb, prob, 8);
     }
 
     // Write out the chosen coding method.
-    vp9_write_bit(w, pc->temporal_update);
-    if (pc->temporal_update) {
+    vp9_wb_write_bit(wb, cm->temporal_update);
+    if (cm->temporal_update) {
       for (i = 0; i < PREDICTION_PROBS; i++) {
-        const int prob = pc->segment_pred_probs[i];
-        if (prob != MAX_PROB) {
-          vp9_write_bit(w, 1);
-          vp9_write_prob(w, prob);
-        } else {
-          vp9_write_bit(w, 0);
-        }
+        const int prob = cm->segment_pred_probs[i];
+        const int update = prob != MAX_PROB;
+        vp9_wb_write_bit(wb, update);
+        if (update)
+          vp9_wb_write_literal(wb, prob, 8);
       }
     }
   }
 
   // Segmentation data
-  vp9_write_bit(w, xd->update_mb_segmentation_data);
+  vp9_wb_write_bit(wb, xd->update_mb_segmentation_data);
   // segment_reference_frames(cpi);
   if (xd->update_mb_segmentation_data) {
-    vp9_write_bit(w, xd->mb_segment_abs_delta);
+    vp9_wb_write_bit(wb, xd->mb_segment_abs_delta);
 
     for (i = 0; i < MAX_MB_SEGMENTS; i++) {
       for (j = 0; j < SEG_LVL_MAX; j++) {
-        const int data = vp9_get_segdata(xd, i, j);
-        const int data_max = vp9_seg_feature_data_max(j);
+        const int active = vp9_segfeature_active(xd, i, j);
+        vp9_wb_write_bit(wb, active);
+        if (active) {
+          const int data = vp9_get_segdata(xd, i, j);
+          const int data_max = vp9_seg_feature_data_max(j);
 
-        if (vp9_segfeature_active(xd, i, j)) {
-          vp9_write_bit(w, 1);
-
           if (vp9_is_segfeature_signed(j)) {
-            if (data < 0) {
-              vp9_encode_unsigned_max(w, -data, data_max);
-              vp9_write_bit(w, 1);
-            } else {
-              vp9_encode_unsigned_max(w, data, data_max);
-              vp9_write_bit(w, 0);
-            }
+            vp9_encode_unsigned_max(wb, abs(data), data_max);
+            vp9_wb_write_bit(wb, data < 0);
           } else {
-            vp9_encode_unsigned_max(w, data, data_max);
+            vp9_encode_unsigned_max(wb, data, data_max);
           }
-        } else {
-          vp9_write_bit(w, 0);
         }
       }
     }
@@ -1407,6 +1395,24 @@
   }
 }
 
+static void write_tile_info(VP9_COMMON *cm, struct vp9_write_bit_buffer *wb) {
+  int min_log2_tiles, delta_log2_tiles, n_tile_bits, n;
+  vp9_get_tile_n_bits(cm, &min_log2_tiles, &delta_log2_tiles);
+  n_tile_bits = cm->log2_tile_columns - min_log2_tiles;
+  for (n = 0; n < delta_log2_tiles; n++) {
+    if (n_tile_bits--) {
+      vp9_wb_write_bit(wb, 1);
+    } else {
+      vp9_wb_write_bit(wb, 0);
+      break;
+    }
+  }
+
+  vp9_wb_write_bit(wb, cm->log2_tile_rows != 0);
+  if (cm->log2_tile_rows != 0)
+    vp9_wb_write_bit(wb, cm->log2_tile_rows != 1);
+}
+
 void write_uncompressed_header(VP9_COMP *cpi,
                                struct vp9_write_bit_buffer *wb) {
   VP9_COMMON *const cm = &cpi->common;
@@ -1515,6 +1521,9 @@
 
   encode_loopfilter(cm, xd, wb);
   encode_quantization(cm, wb);
+  encode_segmentation(cpi, wb);
+
+  write_tile_info(cm, wb);
 }
 
 void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, unsigned long *size) {
@@ -1545,8 +1554,6 @@
     active_section = 7;
 #endif
 
-  encode_segmentation(cpi, &header_bc);
-
   if (xd->lossless)
     pc->txfm_mode = ONLY_4X4;
   else
@@ -1621,24 +1628,6 @@
     vp9_write_nmv_probs(cpi, xd->allow_high_precision_mv, &header_bc);
   }
 
-  /* tiling */
-  {
-    int min_log2_tiles, delta_log2_tiles, n_tile_bits, n;
-
-    vp9_get_tile_n_bits(pc, &min_log2_tiles, &delta_log2_tiles);
-    n_tile_bits = pc->log2_tile_columns - min_log2_tiles;
-    for (n = 0; n < delta_log2_tiles; n++) {
-      if (n_tile_bits--) {
-        vp9_write_bit(&header_bc, 1);
-      } else {
-        vp9_write_bit(&header_bc, 0);
-        break;
-      }
-    }
-    vp9_write_bit(&header_bc, pc->log2_tile_rows != 0);
-    if (pc->log2_tile_rows != 0)
-      vp9_write_bit(&header_bc, pc->log2_tile_rows != 1);
-  }
 
   vp9_stop_encode(&header_bc);