Merge "Partition the ans experiment into 'ans' and 'rans'" into nextgenv2
diff --git a/aom_dsp/bitreader.h b/aom_dsp/bitreader.h
index bdedbb5..ef2e5e9 100644
--- a/aom_dsp/bitreader.h
+++ b/aom_dsp/bitreader.h
@@ -103,7 +103,7 @@
 }
 
 // Returns the position in the bit reader in bits.
-static INLINE ptrdiff_t aom_reader_tell(const aom_reader *r) {
+static INLINE uint32_t aom_reader_tell(const aom_reader *r) {
 #if CONFIG_ANS
   (void)r;
   assert(0 && "aom_reader_tell() is unimplemented for ANS");
@@ -116,7 +116,7 @@
 }
 
 // Returns the position in the bit reader in 1/8th bits.
-static INLINE ptrdiff_t aom_reader_tell_frac(const aom_reader *r) {
+static INLINE uint32_t aom_reader_tell_frac(const aom_reader *r) {
 #if CONFIG_ANS
   (void)r;
   assert(0 && "aom_reader_tell_frac() is unimplemented for ANS");
diff --git a/aom_dsp/daalaboolreader.c b/aom_dsp/daalaboolreader.c
index f0da8eb..0fc7b14 100644
--- a/aom_dsp/daalaboolreader.c
+++ b/aom_dsp/daalaboolreader.c
@@ -28,10 +28,10 @@
   return r->buffer_end;
 }
 
-ptrdiff_t aom_daala_reader_tell(const daala_reader *r) {
+uint32_t aom_daala_reader_tell(const daala_reader *r) {
   return od_ec_dec_tell(&r->ec);
 }
 
-ptrdiff_t aom_daala_reader_tell_frac(const daala_reader *r) {
+uint32_t aom_daala_reader_tell_frac(const daala_reader *r) {
   return od_ec_dec_tell_frac(&r->ec);
 }
diff --git a/aom_dsp/daalaboolreader.h b/aom_dsp/daalaboolreader.h
index 10dc391..9d6cebd 100644
--- a/aom_dsp/daalaboolreader.h
+++ b/aom_dsp/daalaboolreader.h
@@ -36,8 +36,8 @@
 
 int aom_daala_reader_init(daala_reader *r, const uint8_t *buffer, int size);
 const uint8_t *aom_daala_reader_find_end(daala_reader *r);
-ptrdiff_t aom_daala_reader_tell(const daala_reader *r);
-ptrdiff_t aom_daala_reader_tell_frac(const daala_reader *r);
+uint32_t aom_daala_reader_tell(const daala_reader *r);
+uint32_t aom_daala_reader_tell_frac(const daala_reader *r);
 
 static INLINE int aom_daala_read(daala_reader *r, int prob) {
   if (prob == 128) {
diff --git a/aom_dsp/dkboolreader.h b/aom_dsp/dkboolreader.h
index bc4b02f..add480a 100644
--- a/aom_dsp/dkboolreader.h
+++ b/aom_dsp/dkboolreader.h
@@ -12,6 +12,7 @@
 #ifndef AOM_DSP_DKBOOLREADER_H_
 #define AOM_DSP_DKBOOLREADER_H_
 
+#include <assert.h>
 #include <stddef.h>
 #include <limits.h>
 
@@ -67,10 +68,11 @@
 
 const uint8_t *aom_dk_reader_find_end(struct aom_dk_reader *r);
 
-static INLINE ptrdiff_t aom_dk_reader_tell(const struct aom_dk_reader *r) {
-  const size_t bits_read = (r->buffer - r->buffer_start) * CHAR_BIT;
+static INLINE uint32_t aom_dk_reader_tell(const struct aom_dk_reader *r) {
+  const uint32_t bits_read = (r->buffer - r->buffer_start) * CHAR_BIT;
   const int count =
       (r->count < LOTS_OF_BITS) ? r->count : r->count - LOTS_OF_BITS;
+  assert(r->buffer >= r->buffer_start);
   return bits_read - (count + CHAR_BIT);
 }
 
@@ -78,7 +80,7 @@
    3 => 1/8th bits.*/
 #define DK_BITRES (3)
 
-static INLINE ptrdiff_t aom_dk_reader_tell_frac(const struct aom_dk_reader *r) {
+static INLINE uint32_t aom_dk_reader_tell_frac(const struct aom_dk_reader *r) {
   uint32_t num_bits;
   uint32_t range;
   int l;
diff --git a/aomenc.c b/aomenc.c
index 3f9a87d..373b69d 100644
--- a/aomenc.c
+++ b/aomenc.c
@@ -395,7 +395,11 @@
 static const arg_def_t aq_mode = ARG_DEF(
     NULL, "aq-mode", 1,
     "Adaptive quantization mode (0: off (default), 1: variance 2: complexity, "
-    "3: cyclic refresh, 4: equator360)");
+#if CONFIG_DELTA_Q
+    "3: cyclic refresh, 4: delta quant)");
+#else
+    "3: cyclic refresh)");
+#endif
 static const arg_def_t frame_periodic_boost =
     ARG_DEF(NULL, "frame-boost", 1,
             "Enable frame periodic boost (0: off (default), 1: on)");
diff --git a/av1/common/av1_rtcd_defs.pl b/av1/common/av1_rtcd_defs.pl
index 3e5c229..3e1b02f 100644
--- a/av1/common/av1_rtcd_defs.pl
+++ b/av1/common/av1_rtcd_defs.pl
@@ -779,9 +779,14 @@
   specialize qw/av1_highbd_block_error sse2/;
 
   if (aom_config("CONFIG_AOM_QM") eq "yes") {
-    add_proto qw/void av1_highbd_quantize_fp/, "const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan, const qm_val_t * qm_ptr, const qm_val_t * iqm_ptr";
+    add_proto qw/void av1_highbd_quantize_fp/, "const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan, const qm_val_t * qm_ptr, const qm_val_t * iqm_ptr, int log_scale";
+    specialize qw/av1_highbd_quantize_fp/;
 
-    add_proto qw/void av1_highbd_quantize_fp_32x32/, "const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan, const qm_val_t * qm_ptr, const qm_val_t * iqm_ptr";
+    add_proto qw/void av1_highbd_quantize_fp_32x32/, "const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan, const qm_val_t * qm_ptr, const qm_val_t * iqm_ptr, int log_scale";
+    specialize qw/av1_highbd_quantize_fp_32x32/;
+
+    add_proto qw/void av1_highbd_quantize_b/, "const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan, const qm_val_t * qm_ptr, const qm_val_t * iqm_ptr, int log_scale";
+    specialize qw/av1_highbd_quantize_b/;
   } else {
     add_proto qw/void av1_highbd_quantize_fp/, "const tran_low_t *coeff_ptr, intptr_t n_coeffs, int skip_block, const int16_t *zbin_ptr, const int16_t *round_ptr, const int16_t *quant_ptr, const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr, tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr, const int16_t *scan, const int16_t *iscan, int log_scale";
     specialize qw/av1_highbd_quantize_fp sse4_1/;
diff --git a/av1/common/blockd.h b/av1/common/blockd.h
index cc990ea..3ff4943 100644
--- a/av1/common/blockd.h
+++ b/av1/common/blockd.h
@@ -246,6 +246,9 @@
 #endif  // CONFIG_NEW_QUANT
   /* deringing gain *per-superblock* */
   int8_t dering_gain;
+#if CONFIG_DELTA_Q
+  int current_q_index;
+#endif
 } MB_MODE_INFO;
 
 typedef struct MODE_INFO {
@@ -401,6 +404,11 @@
 #if CONFIG_GLOBAL_MOTION
   Global_Motion_Params *global_motion;
 #endif  // CONFIG_GLOBAL_MOTION
+#if CONFIG_DELTA_Q
+  int prev_qindex;
+  int delta_qindex;
+  int current_qindex;
+#endif
 } MACROBLOCKD;
 
 static INLINE BLOCK_SIZE get_subsize(BLOCK_SIZE bsize,
diff --git a/av1/common/entropymode.c b/av1/common/entropymode.c
index 23e0409..3f6f0da 100644
--- a/av1/common/entropymode.c
+++ b/av1/common/entropymode.c
@@ -364,6 +364,11 @@
     };
 #endif  // CONFIG_MOTION_VAR || !CONFIG_WARPED_MOTION
 
+#if CONFIG_DELTA_Q
+static const aom_prob default_delta_q_probs[DELTA_Q_CONTEXTS] = { 220, 220,
+                                                                  220 };
+#endif
+
 /* Array indices are identical to previously-existing INTRAMODECONTEXTNODES. */
 const aom_tree_index av1_intra_mode_tree[TREE_SIZE(INTRA_MODES)] = {
   -DC_PRED,   2,          /* 0 = DC_NODE */
@@ -1399,6 +1404,9 @@
                      PARTITION_CONTEXTS);
   av1_tree_to_cdf(av1_segment_tree, fc->seg.tree_probs, fc->seg.tree_cdf);
 #endif
+#if CONFIG_DELTA_Q
+  av1_copy(fc->delta_q_prob, default_delta_q_probs);
+#endif
 }
 
 #if CONFIG_DAALA_EC
@@ -1542,6 +1550,12 @@
           av1_switchable_interp_tree, pre_fc->switchable_interp_prob[i],
           counts->switchable_interp[i], fc->switchable_interp_prob[i]);
   }
+
+#if CONFIG_DELTA_Q
+  for (i = 0; i < DELTA_Q_CONTEXTS; ++i)
+    fc->delta_q_prob[i] =
+        mode_mv_merge_probs(pre_fc->delta_q_prob[i], counts->delta_q[i]);
+#endif
 }
 
 void av1_adapt_intra_frame_probs(AV1_COMMON *cm) {
@@ -1644,6 +1658,11 @@
   }
 #endif  // CONFIG_EXT_PARTITION_TYPES
 
+#if CONFIG_DELTA_Q
+  for (i = 0; i < DELTA_Q_CONTEXTS; ++i)
+    fc->delta_q_prob[i] =
+        mode_mv_merge_probs(pre_fc->delta_q_prob[i], counts->delta_q[i]);
+#endif
 #if CONFIG_EXT_INTRA
   for (i = 0; i < PLANE_TYPES; ++i) {
     fc->ext_intra_probs[i] = av1_mode_mv_merge_probs(pre_fc->ext_intra_probs[i],
diff --git a/av1/common/entropymode.h b/av1/common/entropymode.h
index 769eb2b..02643c0 100644
--- a/av1/common/entropymode.h
+++ b/av1/common/entropymode.h
@@ -138,6 +138,9 @@
   aom_cdf_prob intra_ext_tx_cdf[EXT_TX_SIZES][TX_TYPES][TX_TYPES];
   aom_cdf_prob inter_ext_tx_cdf[EXT_TX_SIZES][TX_TYPES];
 #endif
+#if CONFIG_DELTA_Q
+  aom_prob delta_q_prob[DELTA_Q_CONTEXTS];
+#endif
 } FRAME_CONTEXT;
 
 typedef struct FRAME_COUNTS {
@@ -203,6 +206,9 @@
 #else
   nmv_context_counts mv;
 #endif
+#if CONFIG_DELTA_Q
+  unsigned int delta_q[DELTA_Q_CONTEXTS][2];
+#endif
 #if CONFIG_EXT_TX
 #if CONFIG_RECT_TX
   unsigned int tx_size_implied[TX_SIZES][TX_SIZES];
diff --git a/av1/common/enums.h b/av1/common/enums.h
index 79c0f18..ce6032b 100644
--- a/av1/common/enums.h
+++ b/av1/common/enums.h
@@ -371,6 +371,11 @@
 #endif
 
 #define INTER_MODE_CONTEXTS 7
+#if CONFIG_DELTA_Q
+#define DELTA_Q_SMALL 3
+#define DELTA_Q_CONTEXTS (DELTA_Q_SMALL)
+#define DEFAULT_DELTA_Q_RES 4
+#endif
 
 /* Segment Feature Masks */
 #define MAX_MV_REF_CANDIDATES 2
diff --git a/av1/common/onyxc_int.h b/av1/common/onyxc_int.h
index cf8d7b4..bbcedc4 100644
--- a/av1/common/onyxc_int.h
+++ b/av1/common/onyxc_int.h
@@ -395,6 +395,11 @@
 #if CONFIG_DERING
   int dering_level;
 #endif
+#if CONFIG_DELTA_Q
+  int delta_q_present_flag;
+  // Resolution of delta quant
+  int delta_q_res;
+#endif
 } AV1_COMMON;
 
 // TODO(hkuang): Don't need to lock the whole pool after implementing atomic
@@ -498,7 +503,6 @@
     }
     xd->fc = cm->fc;
   }
-
   xd->above_seg_context = cm->above_seg_context;
 #if CONFIG_VAR_TX
   xd->above_txfm_context = cm->above_txfm_context;
diff --git a/av1/common/thread_common.c b/av1/common/thread_common.c
index 849450d..eeaeb21 100644
--- a/av1/common/thread_common.c
+++ b/av1/common/thread_common.c
@@ -341,4 +341,9 @@
   unsigned int i;
 
   for (i = 0; i < n_counts; i++) acc[i] += cnt[i];
+
+#if CONFIG_DELTA_Q
+  for (i = 0; i < DELTA_Q_CONTEXTS; i++)
+    for (j = 0; j < 2; ++j) cm->counts.delta_q[i][j] += counts->delta_q[i][j];
+#endif
 }
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index 5550a73..0fbf659 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -1209,6 +1209,26 @@
   }
 #endif  // CONFIG_SUPERTX
 
+#if CONFIG_DELTA_Q
+  if (cm->delta_q_present_flag) {
+    int i;
+    for (i = 0; i < MAX_SEGMENTS; i++) {
+      xd->plane[0].seg_dequant[i][0] =
+          av1_dc_quant(xd->current_qindex, cm->y_dc_delta_q, cm->bit_depth);
+      xd->plane[0].seg_dequant[i][1] =
+          av1_ac_quant(xd->current_qindex, 0, cm->bit_depth);
+      xd->plane[1].seg_dequant[i][0] =
+          av1_dc_quant(xd->current_qindex, cm->uv_dc_delta_q, cm->bit_depth);
+      xd->plane[1].seg_dequant[i][1] =
+          av1_ac_quant(xd->current_qindex, cm->uv_ac_delta_q, cm->bit_depth);
+      xd->plane[2].seg_dequant[i][0] =
+          av1_dc_quant(xd->current_qindex, cm->uv_dc_delta_q, cm->bit_depth);
+      xd->plane[2].seg_dequant[i][1] =
+          av1_ac_quant(xd->current_qindex, cm->uv_ac_delta_q, cm->bit_depth);
+    }
+  }
+#endif
+
   if (mbmi->skip) {
     dec_reset_skip_context(xd);
   }
@@ -3370,7 +3390,15 @@
         cm->ref_frame_sign_bias[LAST_FRAME + i] = aom_rb_read_bit(rb);
       }
 
+#if CONFIG_FRAME_SIZE
+      if (cm->error_resilient_mode == 0) {
+        setup_frame_size_with_refs(cm, rb);
+      } else {
+        setup_frame_size(cm, rb);
+      }
+#else
       setup_frame_size_with_refs(cm, rb);
+#endif
 
       cm->allow_high_precision_mv = aom_rb_read_bit(rb);
       cm->interp_filter = read_interp_filter(rb);
@@ -3477,6 +3505,29 @@
 
   setup_segmentation(cm, rb);
 
+#if CONFIG_DELTA_Q
+  {
+    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;
+      }
+    }
+
+    cm->delta_q_res = 1;
+    if (segment_quantizer_active == 0) {
+      cm->delta_q_present_flag = aom_rb_read_bit(rb);
+    } else {
+      cm->delta_q_present_flag = 0;
+    }
+    if (cm->delta_q_present_flag) {
+      xd->prev_qindex = cm->base_qindex;
+      cm->delta_q_res = 1 << aom_rb_read_literal(rb, 2);
+    }
+  }
+#endif
+
   for (i = 0; i < MAX_SEGMENTS; ++i) {
     const int qindex = cm->seg.enabled
                            ? av1_get_qindex(&cm->seg, i, cm->base_qindex)
@@ -3675,6 +3726,11 @@
   for (k = 0; k < SKIP_CONTEXTS; ++k)
     av1_diff_update_prob(&r, &fc->skip_probs[k], ACCT_STR);
 
+#if CONFIG_DELTA_Q
+  for (k = 0; k < DELTA_Q_CONTEXTS; ++k)
+    av1_diff_update_prob(&r, &fc->delta_q_prob[k], ACCT_STR);
+#endif
+
   if (cm->seg.enabled && cm->seg.update_map) {
     if (cm->seg.temporal_update) {
       for (k = 0; k < PREDICTION_PROBS; k++)
diff --git a/av1/decoder/decodemv.c b/av1/decoder/decodemv.c
index 66056c0..ed2fc4c 100644
--- a/av1/decoder/decodemv.c
+++ b/av1/decoder/decodemv.c
@@ -46,6 +46,42 @@
   return (PREDICTION_MODE)aom_read_tree(r, av1_intra_mode_tree, p, ACCT_STR);
 }
 
+#if CONFIG_DELTA_Q
+static int read_delta_qindex(AV1_COMMON *cm, MACROBLOCKD *xd, aom_reader *r,
+                             MB_MODE_INFO *const mbmi, int mi_col, int mi_row) {
+  FRAME_COUNTS *counts = xd->counts;
+  int sign, abs, reduced_delta_qindex = 0;
+  BLOCK_SIZE bsize = mbmi->sb_type;
+  const int b_col = mi_col & MAX_MIB_MASK;
+  const int b_row = mi_row & MAX_MIB_MASK;
+  const int read_delta_q_flag = (b_col == 0 && b_row == 0);
+  int rem_bits, thr, bit = 1;
+
+  if ((bsize != BLOCK_64X64 || mbmi->skip == 0) && read_delta_q_flag) {
+    abs = 0;
+    while (abs < DELTA_Q_SMALL && bit) {
+      bit = aom_read(r, cm->fc->delta_q_prob[abs], ACCT_STR);
+      if (counts) counts->delta_q[abs][bit]++;
+      abs += bit;
+    }
+    if (abs == DELTA_Q_SMALL) {
+      rem_bits = aom_read_literal(r, 3, ACCT_STR);
+      thr = (1 << rem_bits) + 1;
+      abs = aom_read_literal(r, rem_bits, ACCT_STR) + thr;
+    }
+
+    if (abs) {
+      sign = aom_read_bit(r, ACCT_STR);
+    } else {
+      sign = 1;
+    }
+
+    reduced_delta_qindex = sign ? -abs : abs;
+  }
+  return reduced_delta_qindex;
+}
+#endif
+
 static PREDICTION_MODE read_intra_mode_y(AV1_COMMON *cm, MACROBLOCKD *xd,
                                          aom_reader *r, int size_group) {
   const PREDICTION_MODE y_mode =
@@ -598,6 +634,16 @@
 
   mbmi->segment_id = read_intra_segment_id(cm, xd, mi_offset, x_mis, y_mis, r);
   mbmi->skip = read_skip(cm, xd, mbmi->segment_id, r);
+
+#if CONFIG_DELTA_Q
+  if (cm->delta_q_present_flag) {
+    xd->current_qindex =
+        xd->prev_qindex +
+        read_delta_qindex(cm, xd, r, mbmi, mi_col, mi_row) * cm->delta_q_res;
+    xd->prev_qindex = xd->current_qindex;
+  }
+#endif
+
   mbmi->tx_size = read_tx_size_intra(cm, xd, r);
   mbmi->ref_frame[0] = INTRA_FRAME;
   mbmi->ref_frame[1] = NONE;
@@ -1655,6 +1701,14 @@
   if (!supertx_enabled) {
 #endif  // CONFIG_SUPERTX
     mbmi->skip = read_skip(cm, xd, mbmi->segment_id, r);
+#if CONFIG_DELTA_Q
+    if (cm->delta_q_present_flag) {
+      xd->current_qindex =
+          xd->prev_qindex +
+          read_delta_qindex(cm, xd, r, mbmi, mi_col, mi_row) * cm->delta_q_res;
+      xd->prev_qindex = xd->current_qindex;
+    }
+#endif
     inter_block = read_is_inter_block(cm, xd, mbmi->segment_id, r);
 
 #if CONFIG_VAR_TX
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 4f650e9..6326001 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -33,6 +33,7 @@
 #include "av1/common/entropymode.h"
 #include "av1/common/entropymv.h"
 #include "av1/common/mvref_common.h"
+#include "av1/common/odintrin.h"
 #include "av1/common/pred_common.h"
 #include "av1/common/reconinter.h"
 #include "av1/common/seg_common.h"
@@ -488,6 +489,41 @@
   }
 }
 
+#if CONFIG_DELTA_Q
+static void write_delta_qindex(const AV1_COMMON *cm, int delta_qindex,
+                               aom_writer *w) {
+  int sign = delta_qindex < 0;
+  int abs = sign ? -delta_qindex : delta_qindex;
+  int rem_bits, thr, i = 0;
+  int smallval = abs < DELTA_Q_SMALL ? 1 : 0;
+
+  while (i < DELTA_Q_SMALL && i <= abs) {
+    int bit = (i < abs);
+    aom_write(w, bit, cm->fc->delta_q_prob[i]);
+    i++;
+  }
+
+  if (!smallval) {
+    rem_bits = OD_ILOG_NZ(abs - 1) - 1;
+    thr = (1 << rem_bits) + 1;
+    aom_write_literal(w, rem_bits, 3);
+    aom_write_literal(w, abs - thr, rem_bits);
+  }
+  if (abs > 0) {
+    aom_write_bit(w, sign);
+  }
+}
+
+static void update_delta_q_probs(AV1_COMMON *cm, aom_writer *w,
+                                 FRAME_COUNTS *counts) {
+  int k;
+
+  for (k = 0; k < DELTA_Q_CONTEXTS; ++k) {
+    av1_cond_prob_diff_update(w, &cm->fc->delta_q_prob[k], counts->delta_q[k]);
+  }
+}
+#endif
+
 static void update_skip_probs(AV1_COMMON *cm, aom_writer *w,
                               FRAME_COUNTS *counts) {
   int k;
@@ -1069,8 +1105,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 +1144,20 @@
 #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) >> (MI_SIZE_LOG2 + 3);
+    int mi_col = (-xd->mb_to_left_edge) >> (MI_SIZE_LOG2 + 3);
+    int super_block_upper_left =
+        ((mi_row & MAX_MIB_MASK) == 0) && ((mi_col & MAX_MIB_MASK) == 0);
+    if ((bsize != BLOCK_64X64 || skip == 0) && super_block_upper_left) {
+      int reduced_delta_qindex =
+          (mbmi->current_q_index - xd->prev_qindex) / cm->delta_q_res;
+      write_delta_qindex(cm, reduced_delta_qindex, w);
+      xd->prev_qindex = mbmi->current_q_index;
+    }
+  }
+#endif
 
 #if CONFIG_SUPERTX
   if (!supertx_enabled)
@@ -1503,8 +1559,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 +1577,22 @@
 
   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 reduced_delta_qindex =
+          (mbmi->current_q_index - xd->prev_qindex) / cm->delta_q_res;
+      write_delta_qindex(cm, reduced_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 +2077,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);
@@ -3292,7 +3373,15 @@
         aom_wb_write_bit(wb, cm->ref_frame_sign_bias[ref_frame]);
       }
 
+#if CONFIG_FRAME_SIZE
+      if (cm->error_resilient_mode == 0) {
+        write_frame_size_with_refs(cpi, wb);
+      } else {
+        write_frame_size(cm, wb);
+      }
+#else
       write_frame_size_with_refs(cpi, wb);
+#endif
 
       aom_wb_write_bit(wb, cm->allow_high_precision_mv);
 
@@ -3329,6 +3418,27 @@
 #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) {
+        aom_wb_write_literal(wb, OD_ILOG_NZ(cm->delta_q_res) - 1, 2);
+        xd->prev_qindex = cm->base_qindex;
+      }
+    }
+  }
+#endif
+
   if (!cm->seg.enabled && xd->lossless[0])
     cm->tx_mode = ONLY_4X4;
   else
@@ -3444,6 +3554,9 @@
 #endif
 
   update_skip_probs(cm, header_bc, counts);
+#if CONFIG_DELTA_Q
+  update_delta_q_probs(cm, header_bc, counts);
+#endif
   update_seg_probs(cpi, header_bc);
 
   for (i = 0; i < INTRA_MODES; ++i)
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 004ad68..66de9c6 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -1114,8 +1114,13 @@
         xd->mi[x_idx + y * mis] = mi_addr;
       }
 
+#if CONFIG_DELTA_Q
+  if (cpi->oxcf.aq_mode > NO_AQ && cpi->oxcf.aq_mode < DELTA_AQ)
+    av1_init_plane_quantizers(cpi, x);
+#else
   if (cpi->oxcf.aq_mode)
     av1_init_plane_quantizers(cpi, x, xd->mi[0]->mbmi.segment_id);
+#endif
 
   if (is_inter_block(mbmi) && mbmi->sb_type < BLOCK_8X8) {
     mbmi->mv[0].as_int = mi->bmi[3].as_mv[0].as_int;
@@ -1799,13 +1804,34 @@
                          int supertx_enabled
 #endif
                          ) {
+#if CONFIG_DELTA_Q
+  MACROBLOCK *x = &td->mb;
+  MACROBLOCKD *const xd = &x->e_mbd;
+#else
   const MACROBLOCK *x = &td->mb;
   const MACROBLOCKD *const xd = &x->e_mbd;
+#endif
   const MODE_INFO *const mi = xd->mi[0];
   const MB_MODE_INFO *const mbmi = &mi->mbmi;
   const MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
   const BLOCK_SIZE bsize = mbmi->sb_type;
 
+#if CONFIG_DELTA_Q
+  // delta quant applies to both intra and inter
+  const int super_block_upper_left = ((mi_row & 7) == 0) && ((mi_col & 7) == 0);
+
+  if (cm->delta_q_present_flag && (bsize != BLOCK_64X64 || !mbmi->skip) &&
+      super_block_upper_left) {
+    const int dq = (mbmi->current_q_index - xd->prev_qindex) / cm->delta_q_res;
+    const int absdq = abs(dq);
+    int i;
+    for (i = 0; i < absdq; ++i) {
+      td->counts->delta_q[i][1]++;
+    }
+    if (absdq < DELTA_Q_SMALL) td->counts->delta_q[absdq][0]++;
+    xd->prev_qindex = mbmi->current_q_index;
+  }
+#endif
   if (!frame_is_intra_only(cm)) {
     FRAME_COUNTS *const counts = td->counts;
     const int inter_block = is_inter_block(mbmi);
@@ -4149,6 +4175,12 @@
   // Initialize the left context for the new SB row
   av1_zero_left_context(xd);
 
+#if CONFIG_DELTA_Q
+  // Reset delta for every tile
+  if (cm->delta_q_present_flag)
+    if (mi_row == tile_info->mi_row_start) xd->prev_qindex = cm->base_qindex;
+#endif
+
   // Code each SB in the row
   for (mi_col = tile_info->mi_col_start; mi_col < tile_info->mi_col_end;
        mi_col += cm->mib_size) {
@@ -4188,6 +4220,31 @@
       seg_skip = segfeature_active(seg, segment_id, SEG_LVL_SKIP);
     }
 
+#if CONFIG_DELTA_Q
+    if (cpi->oxcf.aq_mode == DELTA_AQ) {
+      // Test mode for delta quantization
+      int sb_row = mi_row >> 3;
+      int sb_col = mi_col >> 3;
+      int sb_stride = (cm->width + MAX_SB_SIZE - 1) >> MAX_SB_SIZE_LOG2;
+      int index = ((sb_row * sb_stride + sb_col + 8) & 31) - 16;
+
+      // Ensure divisibility of delta_qindex by delta_q_res
+      int offset_qindex = (index < 0 ? -index - 8 : index - 8);
+      int qmask = ~(cm->delta_q_res - 1);
+      int current_qindex = clamp(cm->base_qindex + offset_qindex,
+                                 cm->delta_q_res, 256 - cm->delta_q_res);
+      current_qindex =
+          ((current_qindex - cm->base_qindex + cm->delta_q_res / 2) & qmask) +
+          cm->base_qindex;
+
+      xd->delta_qindex = current_qindex - cm->base_qindex;
+      set_offsets(cpi, tile_info, x, mi_row, mi_col, BLOCK_64X64);
+      xd->mi[0]->mbmi.current_q_index = current_qindex;
+      xd->mi[0]->mbmi.segment_id = 0;
+      av1_init_plane_quantizers(cpi, x);
+    }
+#endif
+
     x->source_variance = UINT_MAX;
     if (sf->partition_search_type == FIXED_PARTITION || seg_skip) {
       BLOCK_SIZE bsize;
@@ -4632,6 +4689,12 @@
   cm->use_prev_frame_mvs =
       !cm->error_resilient_mode && cm->width == cm->last_width &&
       cm->height == cm->last_height && !cm->intra_only && cm->last_show_frame;
+
+#if CONFIG_DELTA_Q
+  // Fix delta q resolution for the moment
+  cm->delta_q_res = DEFAULT_DELTA_Q_RES;
+#endif
+
 #if CONFIG_EXT_REFS
   // NOTE(zoeliu): As cm->prev_frame can take neither a frame of
   //               show_exisiting_frame=1, nor can it take a frame not used as
diff --git a/av1/encoder/encodemb.c b/av1/encoder/encodemb.c
index 192ec47..4ab1b48 100644
--- a/av1/encoder/encodemb.c
+++ b/av1/encoder/encodemb.c
@@ -386,12 +386,6 @@
   for (i = next; i < eob; i = next) {
     const int x = tokens[i][best].qc;
     const int rc = scan[i];
-#if CONFIG_AOM_QM
-    const int iwt = iqmatrix[rc];
-    const int dequant =
-        (dequant_ptr[rc != 0] * iwt + (1 << (AOM_QM_BITS - 1))) >> AOM_QM_BITS;
-#endif
-
     if (x) final_eob = i;
     qcoeff[rc] = x;
     dqcoeff[rc] = tokens[i][best].dqc;
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index e2046ec..b55481b 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -133,6 +133,9 @@
   VARIANCE_AQ = 1,
   COMPLEXITY_AQ = 2,
   CYCLIC_REFRESH_AQ = 3,
+#if CONFIG_DELTA_Q
+  DELTA_AQ = 4,
+#endif
   AQ_MODE_COUNT  // This should always be the last member of the enum
 } AQ_MODE;
 
diff --git a/av1/encoder/quantize.c b/av1/encoder/quantize.c
index 827e6d8..db2fdb8 100644
--- a/av1/encoder/quantize.c
+++ b/av1/encoder/quantize.c
@@ -344,18 +344,33 @@
                             const MACROBLOCK_PLANE *p, tran_low_t *qcoeff_ptr,
                             const MACROBLOCKD_PLANE *pd,
                             tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
-                            const SCAN_ORDER *sc, const QUANT_PARAM *qparam) {
+                            const SCAN_ORDER *sc, const QUANT_PARAM *qparam
+#if CONFIG_AOM_QM
+                            ,
+                            const qm_val_t *qm_ptr, const qm_val_t *iqm_ptr
+#endif
+                            ) {
   // obsolete skip_block
   const int skip_block = 0;
 
   if (qparam->log_scale == 0) {
     av1_quantize_fp(coeff_ptr, n_coeffs, skip_block, p->zbin, p->round_fp,
                     p->quant_fp, p->quant_shift, qcoeff_ptr, dqcoeff_ptr,
-                    pd->dequant, eob_ptr, sc->scan, sc->iscan);
+                    pd->dequant, eob_ptr, sc->scan, sc->iscan
+#if CONFIG_AOM_QM
+                    ,
+                    qm_ptr, iqm_ptr
+#endif
+                    );
   } else {
     av1_quantize_fp_32x32(coeff_ptr, n_coeffs, skip_block, p->zbin, p->round_fp,
                           p->quant_fp, p->quant_shift, qcoeff_ptr, dqcoeff_ptr,
-                          pd->dequant, eob_ptr, sc->scan, sc->iscan);
+                          pd->dequant, eob_ptr, sc->scan, sc->iscan
+#if CONFIG_AOM_QM
+                          ,
+                          qm_ptr, iqm_ptr
+#endif
+                          );
   }
 }
 
@@ -363,18 +378,33 @@
                            const MACROBLOCK_PLANE *p, tran_low_t *qcoeff_ptr,
                            const MACROBLOCKD_PLANE *pd, tran_low_t *dqcoeff_ptr,
                            uint16_t *eob_ptr, const SCAN_ORDER *sc,
-                           const QUANT_PARAM *qparam) {
+                           const QUANT_PARAM *qparam
+#if CONFIG_AOM_QM
+                           ,
+                           const qm_val_t *qm_ptr, const qm_val_t *iqm_ptr
+#endif
+                           ) {
   // obsolete skip_block
   const int skip_block = 0;
 
   if (qparam->log_scale == 0) {
     aom_quantize_b(coeff_ptr, n_coeffs, skip_block, p->zbin, p->round, p->quant,
                    p->quant_shift, qcoeff_ptr, dqcoeff_ptr, pd->dequant,
-                   eob_ptr, sc->scan, sc->iscan);
+                   eob_ptr, sc->scan, sc->iscan
+#if CONFIG_AOM_QM
+                   ,
+                   qm_ptr, iqm_ptr
+#endif
+                   );
   } else {
     aom_quantize_b_32x32(coeff_ptr, n_coeffs, skip_block, p->zbin, p->round,
                          p->quant, p->quant_shift, qcoeff_ptr, dqcoeff_ptr,
-                         pd->dequant, eob_ptr, sc->scan, sc->iscan);
+                         pd->dequant, eob_ptr, sc->scan, sc->iscan
+#if CONFIG_AOM_QM
+                         ,
+                         qm_ptr, iqm_ptr
+#endif
+                         );
   }
 }
 
@@ -382,60 +412,90 @@
                             const MACROBLOCK_PLANE *p, tran_low_t *qcoeff_ptr,
                             const MACROBLOCKD_PLANE *pd,
                             tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
-                            const SCAN_ORDER *sc, const QUANT_PARAM *qparam) {
+                            const SCAN_ORDER *sc, const QUANT_PARAM *qparam
+#if CONFIG_AOM_QM
+                            ,
+                            const qm_val_t *qm_ptr, const qm_val_t *iqm_ptr
+#endif
+                            ) {
   // obsolete skip_block
   const int skip_block = 0;
   (void)sc;
   if (qparam->log_scale == 0) {
     aom_quantize_dc(coeff_ptr, (int)n_coeffs, skip_block, p->round,
                     p->quant_fp[0], qcoeff_ptr, dqcoeff_ptr, pd->dequant[0],
-                    eob_ptr);
+                    eob_ptr
+#if CONFIG_AOM_QM
+                    ,
+                    qm_ptr, iqm_ptr
+#endif
+                    );
   } else {
     aom_quantize_dc_32x32(coeff_ptr, skip_block, p->round, p->quant_fp[0],
-                          qcoeff_ptr, dqcoeff_ptr, pd->dequant[0], eob_ptr);
+                          qcoeff_ptr, dqcoeff_ptr, pd->dequant[0], eob_ptr
+#if CONFIG_AOM_QM
+                          ,
+                          qm_ptr, iqm_ptr
+#endif
+                          );
   }
 }
 
 #if CONFIG_AOM_HIGHBITDEPTH
-void av1_highbd_quantize_fp_facade(const tran_low_t *coeff_ptr,
-                                   intptr_t n_coeffs, const MACROBLOCK_PLANE *p,
-                                   tran_low_t *qcoeff_ptr,
-                                   const MACROBLOCKD_PLANE *pd,
-                                   tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
-                                   const SCAN_ORDER *sc,
-                                   const QUANT_PARAM *qparam) {
+void av1_highbd_quantize_fp_facade(
+    const tran_low_t *coeff_ptr, intptr_t n_coeffs, const MACROBLOCK_PLANE *p,
+    tran_low_t *qcoeff_ptr, const MACROBLOCKD_PLANE *pd,
+    tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr, const SCAN_ORDER *sc,
+    const QUANT_PARAM *qparam
+#if CONFIG_AOM_QM
+    ,
+    const qm_val_t *qm_ptr, const qm_val_t *iqm_ptr
+#endif
+    ) {
   // obsolete skip_block
   const int skip_block = 0;
 
   av1_highbd_quantize_fp(coeff_ptr, n_coeffs, skip_block, p->zbin, p->round_fp,
                          p->quant_fp, p->quant_shift, qcoeff_ptr, dqcoeff_ptr,
                          pd->dequant, eob_ptr, sc->scan, sc->iscan,
+#if CONFIG_AOM_QM
+                         qm_ptr, iqm_ptr,
+#endif
                          qparam->log_scale);
 }
 
-void av1_highbd_quantize_b_facade(const tran_low_t *coeff_ptr,
-                                  intptr_t n_coeffs, const MACROBLOCK_PLANE *p,
-                                  tran_low_t *qcoeff_ptr,
-                                  const MACROBLOCKD_PLANE *pd,
-                                  tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
-                                  const SCAN_ORDER *sc,
-                                  const QUANT_PARAM *qparam) {
+void av1_highbd_quantize_b_facade(
+    const tran_low_t *coeff_ptr, intptr_t n_coeffs, const MACROBLOCK_PLANE *p,
+    tran_low_t *qcoeff_ptr, const MACROBLOCKD_PLANE *pd,
+    tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr, const SCAN_ORDER *sc,
+    const QUANT_PARAM *qparam
+#if CONFIG_AOM_QM
+    ,
+    const qm_val_t *qm_ptr, const qm_val_t *iqm_ptr
+#endif
+    ) {
   // obsolete skip_block
   const int skip_block = 0;
 
   av1_highbd_quantize_b(coeff_ptr, n_coeffs, skip_block, p->zbin, p->round,
                         p->quant, p->quant_shift, qcoeff_ptr, dqcoeff_ptr,
                         pd->dequant, eob_ptr, sc->scan, sc->iscan,
+#if CONFIG_AOM_QM
+                        qm_ptr, iqm_ptr,
+#endif
                         qparam->log_scale);
 }
 
-void av1_highbd_quantize_dc_facade(const tran_low_t *coeff_ptr,
-                                   intptr_t n_coeffs, const MACROBLOCK_PLANE *p,
-                                   tran_low_t *qcoeff_ptr,
-                                   const MACROBLOCKD_PLANE *pd,
-                                   tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
-                                   const SCAN_ORDER *sc,
-                                   const QUANT_PARAM *qparam) {
+void av1_highbd_quantize_dc_facade(
+    const tran_low_t *coeff_ptr, intptr_t n_coeffs, const MACROBLOCK_PLANE *p,
+    tran_low_t *qcoeff_ptr, const MACROBLOCKD_PLANE *pd,
+    tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr, const SCAN_ORDER *sc,
+    const QUANT_PARAM *qparam
+#if CONFIG_AOM_QM
+    ,
+    const qm_val_t *qm_ptr, const qm_val_t *iqm_ptr
+#endif
+    ) {
   // obsolete skip_block
   const int skip_block = 0;
 
@@ -443,7 +503,11 @@
 
   av1_highbd_quantize_dc(coeff_ptr, (int)n_coeffs, skip_block, p->round,
                          p->quant_fp[0], qcoeff_ptr, dqcoeff_ptr,
-                         pd->dequant[0], eob_ptr, qparam->log_scale);
+                         pd->dequant[0], eob_ptr,
+#if CONFIG_AOM_QM
+                         qm_ptr, iqm_ptr,
+#endif
+                         qparam->log_scale);
 }
 
 #if CONFIG_NEW_QUANT
@@ -975,15 +1039,6 @@
     for (i = (int)n_coeffs - 1; i >= 0; i--) {
       const int rc = scan[i];
       const int coeff = coeff_ptr[rc];
-#if CONFIG_AOM_QM
-      uint32_t abs_qcoeff = 0;
-      const qm_val_t wt = qm_ptr[rc];
-      const qm_val_t iwt = iqm_ptr[rc];
-      const int dequant =
-          (dequant_ptr[rc != 0] * iwt + (1 << (AOM_QM_BITS - 1))) >>
-          AOM_QM_BITS;
-#endif
-
       if (coeff < zbins[rc != 0] && coeff > nzbins[rc != 0])
         non_zero_count--;
       else
@@ -994,6 +1049,13 @@
     // skippable. Note: zero_flag can be zero.
     for (i = 0; i < non_zero_count; i++) {
       const int rc = scan[i];
+#if CONFIG_AOM_QM
+      const qm_val_t wt = qm_ptr[rc];
+      const qm_val_t iwt = iqm_ptr[rc];
+      const int dequant =
+          (dequant_ptr[rc != 0] * iwt + (1 << (AOM_QM_BITS - 1))) >>
+          AOM_QM_BITS;
+#endif
       const int coeff = coeff_ptr[rc];
       const int coeff_sign = (coeff >> 31);
       const int abs_coeff = (coeff ^ coeff_sign) - coeff_sign;
@@ -1029,12 +1091,19 @@
                             int skip_block, const int16_t *round_ptr,
                             const int16_t quant, tran_low_t *qcoeff_ptr,
                             tran_low_t *dqcoeff_ptr, const int16_t dequant_ptr,
-                            uint16_t *eob_ptr, const int log_scale) {
+                            uint16_t *eob_ptr,
+#if CONFIG_AOM_QM
+                            const qm_val_t *qm_ptr, const qm_val_t *iqm_ptr,
+#endif
+                            const int log_scale) {
   int eob = -1;
 
   memset(qcoeff_ptr, 0, n_coeffs * sizeof(*qcoeff_ptr));
   memset(dqcoeff_ptr, 0, n_coeffs * sizeof(*dqcoeff_ptr));
-
+#if CONFIG_AOM_QM
+  (void)qm_ptr;
+  (void)iqm_ptr;
+#endif
   if (!skip_block) {
     const int coeff = coeff_ptr[0];
     const int coeff_sign = (coeff >> 31);
@@ -1150,14 +1219,22 @@
   const AV1_COMMON *const cm = &cpi->common;
   MACROBLOCKD *const xd = &x->e_mbd;
   const QUANTS *const quants = &cpi->quants;
+
+#if CONFIG_DELTA_Q
+  int current_q_index = cpi->oxcf.aq_mode == DELTA_AQ
+                            ? cm->base_qindex + xd->delta_qindex
+                            : cm->base_qindex;
+  const int qindex = av1_get_qindex(&cm->seg, segment_id, current_q_index);
+#else
   const int qindex = av1_get_qindex(&cm->seg, segment_id, cm->base_qindex);
+#endif
   const int rdmult = av1_compute_rd_mult(cpi, qindex + cm->y_dc_delta_q);
   int i;
 #if CONFIG_AOM_QM
   int minqm = cm->min_qmlevel;
   int maxqm = cm->max_qmlevel;
   // Quant matrix only depends on the base QP so there is only one set per frame
-  int qmlevel = (lossless || cm->using_qmatrix == 0)
+  int qmlevel = (xd->lossless[segment_id] || cm->using_qmatrix == 0)
                     ? NUM_QM_LEVELS - 1
                     : aom_get_qmlevel(cm->base_qindex, minqm, maxqm);
 #endif
diff --git a/av1/encoder/quantize.h b/av1/encoder/quantize.h
index 1c32ee1..f5f045e 100644
--- a/av1/encoder/quantize.h
+++ b/av1/encoder/quantize.h
@@ -28,8 +28,12 @@
                                  tran_low_t *qcoeff_ptr,
                                  const MACROBLOCKD_PLANE *pd,
                                  tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
-                                 const SCAN_ORDER *sc,
-                                 const QUANT_PARAM *qparam);
+                                 const SCAN_ORDER *sc, const QUANT_PARAM *qparam
+#if CONFIG_AOM_QM
+                                 ,
+                                 const qm_val_t *qm_ptr, const qm_val_t *iqm_ptr
+#endif
+                                 );
 
 typedef struct {
 #if CONFIG_NEW_QUANT
@@ -80,19 +84,34 @@
                             const MACROBLOCK_PLANE *p, tran_low_t *qcoeff_ptr,
                             const MACROBLOCKD_PLANE *pd,
                             tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
-                            const SCAN_ORDER *sc, const QUANT_PARAM *qparam);
+                            const SCAN_ORDER *sc, const QUANT_PARAM *qparam
+#if CONFIG_AOM_QM
+                            ,
+                            const qm_val_t *qm_ptr, const qm_val_t *iqm_ptr
+#endif
+                            );
 
 void av1_quantize_b_facade(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
                            const MACROBLOCK_PLANE *p, tran_low_t *qcoeff_ptr,
                            const MACROBLOCKD_PLANE *pd, tran_low_t *dqcoeff_ptr,
                            uint16_t *eob_ptr, const SCAN_ORDER *sc,
-                           const QUANT_PARAM *qparam);
+                           const QUANT_PARAM *qparam
+#if CONFIG_AOM_QM
+                           ,
+                           const qm_val_t *qm_ptr, const qm_val_t *iqm_ptr
+#endif
+                           );
 
 void av1_quantize_dc_facade(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
                             const MACROBLOCK_PLANE *p, tran_low_t *qcoeff_ptr,
                             const MACROBLOCKD_PLANE *pd,
                             tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
-                            const SCAN_ORDER *sc, const QUANT_PARAM *qparam);
+                            const SCAN_ORDER *sc, const QUANT_PARAM *qparam
+#if CONFIG_AOM_QM
+                            ,
+                            const qm_val_t *qm_ptr, const qm_val_t *iqm_ptr
+#endif
+                            );
 
 #if CONFIG_NEW_QUANT
 void quantize_dc_nuq(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
@@ -123,35 +142,48 @@
 #endif  // CONFIG_NEW_QUANT
 
 #if CONFIG_AOM_HIGHBITDEPTH
-void av1_highbd_quantize_fp_facade(const tran_low_t *coeff_ptr,
-                                   intptr_t n_coeffs, const MACROBLOCK_PLANE *p,
-                                   tran_low_t *qcoeff_ptr,
-                                   const MACROBLOCKD_PLANE *pd,
-                                   tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
-                                   const SCAN_ORDER *sc,
-                                   const QUANT_PARAM *qparam);
+void av1_highbd_quantize_fp_facade(
+    const tran_low_t *coeff_ptr, intptr_t n_coeffs, const MACROBLOCK_PLANE *p,
+    tran_low_t *qcoeff_ptr, const MACROBLOCKD_PLANE *pd,
+    tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr, const SCAN_ORDER *sc,
+    const QUANT_PARAM *qparam
+#if CONFIG_AOM_QM
+    ,
+    const qm_val_t *qm_ptr, const qm_val_t *iqm_ptr
+#endif
+    );
 
-void av1_highbd_quantize_b_facade(const tran_low_t *coeff_ptr,
-                                  intptr_t n_coeffs, const MACROBLOCK_PLANE *p,
-                                  tran_low_t *qcoeff_ptr,
-                                  const MACROBLOCKD_PLANE *pd,
-                                  tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
-                                  const SCAN_ORDER *sc,
-                                  const QUANT_PARAM *qparam);
+void av1_highbd_quantize_b_facade(
+    const tran_low_t *coeff_ptr, intptr_t n_coeffs, const MACROBLOCK_PLANE *p,
+    tran_low_t *qcoeff_ptr, const MACROBLOCKD_PLANE *pd,
+    tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr, const SCAN_ORDER *sc,
+    const QUANT_PARAM *qparam
+#if CONFIG_AOM_QM
+    ,
+    const qm_val_t *qm_ptr, const qm_val_t *iqm_ptr
+#endif
+    );
 
-void av1_highbd_quantize_dc_facade(const tran_low_t *coeff_ptr,
-                                   intptr_t n_coeffs, const MACROBLOCK_PLANE *p,
-                                   tran_low_t *qcoeff_ptr,
-                                   const MACROBLOCKD_PLANE *pd,
-                                   tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr,
-                                   const SCAN_ORDER *sc,
-                                   const QUANT_PARAM *qparam);
+void av1_highbd_quantize_dc_facade(
+    const tran_low_t *coeff_ptr, intptr_t n_coeffs, const MACROBLOCK_PLANE *p,
+    tran_low_t *qcoeff_ptr, const MACROBLOCKD_PLANE *pd,
+    tran_low_t *dqcoeff_ptr, uint16_t *eob_ptr, const SCAN_ORDER *sc,
+    const QUANT_PARAM *qparam
+#if CONFIG_AOM_QM
+    ,
+    const qm_val_t *qm_ptr, const qm_val_t *iqm_ptr
+#endif
+    );
 
 void av1_highbd_quantize_dc(const tran_low_t *coeff_ptr, int n_coeffs,
                             int skip_block, const int16_t *round_ptr,
                             const int16_t quant, tran_low_t *qcoeff_ptr,
                             tran_low_t *dqcoeff_ptr, const int16_t dequant_ptr,
-                            uint16_t *eob_ptr, const int log_scale);
+                            uint16_t *eob_ptr,
+#if CONFIG_AOM_QM
+                            const qm_val_t *qm_ptr, const qm_val_t *iqm_ptr,
+#endif
+                            const int log_scale);
 #if CONFIG_NEW_QUANT
 void highbd_quantize_dc_nuq(const tran_low_t *coeff_ptr, intptr_t n_coeffs,
                             int skip_block, const int16_t quant,
diff --git a/configure b/configure
index 358e3da..7901ef3 100755
--- a/configure
+++ b/configure
@@ -276,7 +276,6 @@
     ext_partition
     ext_partition_types
     ext_tile
-    obmc
     motion_var
     warped_motion
     entropy
@@ -286,6 +285,8 @@
     palette
     daala_ec
     cb4x4
+    frame_size
+    delta_q
 "
 CONFIG_LIST="
     dependency_tracking
diff --git a/test/aq_segment_test.cc b/test/aq_segment_test.cc
index 820aaff..e231b4e 100644
--- a/test/aq_segment_test.cc
+++ b/test/aq_segment_test.cc
@@ -9,6 +9,7 @@
  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
 */
 
+#include "./aom_config.h"
 #include "third_party/googletest/src/include/gtest/gtest.h"
 #include "test/codec_factory.h"
 #include "test/encode_test_driver.h"
@@ -80,6 +81,21 @@
 
 TEST_P(AqSegmentTestLarge, TestNoMisMatchAQ3) { DoTest(3); }
 
+#if CONFIG_DELTA_Q
+// Validate that this AQ mode (AQ=4, delta q)
+// encodes and decodes without a mismatch.
+TEST_P(AqSegmentTest, TestNoMisMatchAQ4) {
+  cfg_.rc_end_usage = AOM_CQ;
+
+  aq_mode_ = 4;
+
+  ::libaom_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 100);
+
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+#endif
+
 AV1_INSTANTIATE_TEST_CASE(AqSegmentTest,
                           ::testing::Values(::libaom_test::kRealTime,
                                             ::libaom_test::kOnePassGood),
diff --git a/test/av1_quantize_test.cc b/test/av1_quantize_test.cc
index 4e1aabd..6320090 100644
--- a/test/av1_quantize_test.cc
+++ b/test/av1_quantize_test.cc
@@ -195,6 +195,7 @@
 TEST_P(AV1QuantizeTest, EobVerify) { RunEobTest(); }
 
 #if HAVE_SSE4_1
+#if !CONFIG_AOM_QM
 INSTANTIATE_TEST_CASE_P(
     SSE4_1, AV1QuantizeTest,
     ::testing::Values(QuantizeFuncParams(&av1_highbd_quantize_fp_sse4_1,
@@ -205,5 +206,6 @@
                                          &av1_highbd_quantize_fp_c, 256),
                       QuantizeFuncParams(&av1_highbd_quantize_fp_sse4_1,
                                          &av1_highbd_quantize_fp_c, 1024)));
+#endif  // !CONFIG_AOM_QM
 #endif  // HAVE_SSE4_1
 }  // namespace
diff --git a/test/boolcoder_test.cc b/test/boolcoder_test.cc
index 1000f58..c0e6d48 100644
--- a/test/boolcoder_test.cc
+++ b/test/boolcoder_test.cc
@@ -68,11 +68,13 @@
 
         aom_stop_encode(&bw);
 
+#if !CONFIG_DAALA_EC
         // First bit should be zero
         GTEST_ASSERT_EQ(bw_buffer[0] & 0x80, 0);
+#endif
 
         aom_reader br;
-        aom_reader_init(&br, bw_buffer, kBufferSize, NULL, NULL);
+        aom_reader_init(&br, bw_buffer, bw.pos, NULL, NULL);
         bit_rnd.Reset(random_seed);
         for (int i = 0; i < kBitsToTest; ++i) {
           if (bit_method == 2) {
@@ -110,15 +112,15 @@
     aom_stop_encode(&bw);
     aom_reader br;
     aom_reader_init(&br, bw_buffer, kBufferSize, NULL, NULL);
-    ptrdiff_t last_tell = aom_reader_tell(&br);
-    ptrdiff_t last_tell_frac = aom_reader_tell_frac(&br);
+    uint32_t last_tell = aom_reader_tell(&br);
+    uint32_t last_tell_frac = aom_reader_tell_frac(&br);
     double frac_diff_total = 0;
-    GTEST_ASSERT_GE(aom_reader_tell(&br), 0);
-    GTEST_ASSERT_LE(aom_reader_tell(&br), 1);
+    GTEST_ASSERT_GE(aom_reader_tell(&br), 0u);
+    GTEST_ASSERT_LE(aom_reader_tell(&br), 1u);
     for (int i = 0; i < kSymbols; i++) {
       aom_read(&br, p, NULL);
-      ptrdiff_t tell = aom_reader_tell(&br);
-      ptrdiff_t tell_frac = aom_reader_tell_frac(&br);
+      uint32_t tell = aom_reader_tell(&br);
+      uint32_t tell_frac = aom_reader_tell_frac(&br);
       GTEST_ASSERT_GE(tell, last_tell) << "tell: " << tell
                                        << ", last_tell: " << last_tell;
       GTEST_ASSERT_GE(tell_frac, last_tell_frac)
@@ -131,7 +133,7 @@
           fabs(((tell_frac - last_tell_frac) / 8.0) + log2(probability));
       last_tell_frac = tell_frac;
     }
-    const int expected = (int)(-kSymbols * log2(probability));
+    const uint32_t expected = (uint32_t)(-kSymbols * log2(probability));
     // Last tell should be close to the expected value.
     GTEST_ASSERT_LE(last_tell - expected, 20) << " last_tell: " << last_tell;
     // The average frac_diff error should be pretty small.