Support for delta-q at superblock level

Change-Id: I4128af44776d1f361bddc1fdffb75ed2224dbfa5
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index b7cbc00..fe6ffe7 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -488,6 +488,22 @@
   }
 }
 
+#if CONFIG_DELTA_Q
+static void write_delta_qindex(int delta_qindex, aom_writer *w) {
+  int sign = delta_qindex < 0;
+  int abs = sign ? -delta_qindex : delta_qindex;
+  if (abs < 3) {
+    aom_write_literal(w, 1, abs + 1);
+  } else {
+    aom_write_literal(w, 0, 3);
+    aom_write_literal(w, abs, 6);
+  }
+  if (abs > 0) {
+    aom_write_bit(w, sign);
+  }
+}
+#endif
+
 static void update_skip_probs(AV1_COMMON *cm, aom_writer *w,
                               FRAME_COUNTS *counts) {
   int k;
@@ -1069,8 +1085,14 @@
 #if !CONFIG_REF_MV
   const nmv_context *nmvc = &cm->fc->nmvc;
 #endif
+
+#if CONFIG_DELTA_Q
+  MACROBLOCK *const x = &cpi->td.mb;
+  MACROBLOCKD *const xd = &x->e_mbd;
+#else
   const MACROBLOCK *x = &cpi->td.mb;
   const MACROBLOCKD *xd = &x->e_mbd;
+#endif
   const struct segmentation *const seg = &cm->seg;
   const struct segmentation_probs *const segp = &cm->fc->seg;
   const MB_MODE_INFO *const mbmi = &mi->mbmi;
@@ -1102,6 +1124,18 @@
 #else
   skip = write_skip(cm, xd, segment_id, mi, w);
 #endif  // CONFIG_SUPERTX
+#if CONFIG_DELTA_Q
+  if (cm->delta_q_present_flag) {
+    int mi_row = (-xd->mb_to_top_edge) >> 6;
+    int mi_col = (-xd->mb_to_left_edge) >> 6;
+    int super_block_upper_left = ((mi_row & 7) == 0) && ((mi_col & 7) == 0);
+    if ((bsize != BLOCK_64X64 || skip == 0) && super_block_upper_left) {
+      int delta_qindex = mbmi->current_q_index - xd->prev_qindex;
+      write_delta_qindex(delta_qindex, w);
+      xd->prev_qindex = mbmi->current_q_index;
+    }
+  }
+#endif
 
 #if CONFIG_SUPERTX
   if (!supertx_enabled)
@@ -1503,8 +1537,14 @@
   }
 }
 
+#if CONFIG_DELTA_Q
+static void write_mb_modes_kf(const AV1_COMMON *cm, MACROBLOCKD *xd,
+                              MODE_INFO **mi_8x8, aom_writer *w) {
+  int skip;
+#else
 static void write_mb_modes_kf(const AV1_COMMON *cm, const MACROBLOCKD *xd,
                               MODE_INFO **mi_8x8, aom_writer *w) {
+#endif
   const struct segmentation *const seg = &cm->seg;
   const struct segmentation_probs *const segp = &cm->fc->seg;
   const MODE_INFO *const mi = mi_8x8[0];
@@ -1515,7 +1555,21 @@
 
   if (seg->update_map) write_segment_id(w, seg, segp, mbmi->segment_id);
 
+#if CONFIG_DELTA_Q
+  skip = write_skip(cm, xd, mbmi->segment_id, mi, w);
+  if (cm->delta_q_present_flag) {
+    int mi_row = (-xd->mb_to_top_edge) >> 6;
+    int mi_col = (-xd->mb_to_left_edge) >> 6;
+    int super_block_upper_left = ((mi_row & 7) == 0) && ((mi_col & 7) == 0);
+    if ((bsize != BLOCK_64X64 || skip == 0) && super_block_upper_left) {
+      int delta_qindex = mbmi->current_q_index - xd->prev_qindex;
+      write_delta_qindex(delta_qindex, w);
+      xd->prev_qindex = mbmi->current_q_index;
+    }
+  }
+#else
   write_skip(cm, xd, mbmi->segment_id, mi, w);
+#endif
 
   if (bsize >= BLOCK_8X8 && cm->tx_mode == TX_MODE_SELECT &&
       !xd->lossless[mbmi->segment_id])
@@ -2000,8 +2054,12 @@
   const int mi_col_start = tile->mi_col_start;
   const int mi_col_end = tile->mi_col_end;
   int mi_row, mi_col;
-
   av1_zero_above_context(cm, mi_col_start, mi_col_end);
+#if CONFIG_DELTA_Q
+  if (cpi->common.delta_q_present_flag) {
+    xd->prev_qindex = cpi->common.base_qindex;
+  }
+#endif
 
   for (mi_row = mi_row_start; mi_row < mi_row_end; mi_row += cm->mib_size) {
     av1_zero_left_context(xd);
@@ -3337,6 +3395,26 @@
 #endif  // CONFIG_LOOP_RESTORATION
   encode_quantization(cm, wb);
   encode_segmentation(cm, xd, wb);
+#if CONFIG_DELTA_Q
+  {
+    int i;
+    struct segmentation *const seg = &cm->seg;
+    int segment_quantizer_active = 0;
+    for (i = 0; i < MAX_SEGMENTS; i++) {
+      if (segfeature_active(seg, i, SEG_LVL_ALT_Q)) {
+        segment_quantizer_active = 1;
+      }
+    }
+    if (segment_quantizer_active == 0) {
+      cm->delta_q_present_flag = cpi->oxcf.aq_mode == DELTA_AQ;
+      aom_wb_write_bit(wb, cm->delta_q_present_flag);
+      if (cm->delta_q_present_flag) {
+        xd->prev_qindex = cm->base_qindex;
+      }
+    }
+  }
+#endif
+
   if (!cm->seg.enabled && xd->lossless[0])
     cm->tx_mode = ONLY_4X4;
   else