Merge "Change chroma loopfilter to skip inner SB edges for tx16x16 also." into experimental
diff --git a/vp9/common/vp9_blockd.h b/vp9/common/vp9_blockd.h
index 0baadfc..6b4f607 100644
--- a/vp9/common/vp9_blockd.h
+++ b/vp9/common/vp9_blockd.h
@@ -23,7 +23,8 @@
 
 // #define MODE_STATS
 
-#define MB_FEATURE_TREE_PROBS   3
+#define MAX_MB_SEGMENTS     8
+#define MB_SEG_TREE_PROBS   (MAX_MB_SEGMENTS-1)
 #define PREDICTION_PROBS 3
 
 #define DEFAULT_PRED_PROB_0 120
@@ -32,8 +33,6 @@
 
 #define MBSKIP_CONTEXTS 3
 
-#define MAX_MB_SEGMENTS         4
-
 #define MAX_REF_LF_DELTAS       4
 #define MAX_MODE_LF_DELTAS      4
 
@@ -268,7 +267,7 @@
   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;
@@ -336,7 +335,7 @@
   int stride;
 };
 
-struct mb_plane {
+struct macroblockd_plane {
   DECLARE_ALIGNED(16, int16_t,  qcoeff[64 * 64]);
   DECLARE_ALIGNED(16, int16_t,  dqcoeff[64 * 64]);
   DECLARE_ALIGNED(16, uint16_t, eobs[256]);
@@ -356,7 +355,7 @@
   BLOCK_OFFSET((x)->plane[2].field, ((i) - 20), 16))
 
 typedef struct macroblockd {
-  struct mb_plane plane[MAX_MB_PLANE];
+  struct macroblockd_plane plane[MAX_MB_PLANE];
 
   /* 16 Y blocks, 4 U, 4 V, each with 16 entries. */
   BLOCKD block[24];
@@ -384,6 +383,10 @@
   /* 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;
 
@@ -394,8 +397,7 @@
   /* are enabled and when enabled the proabilities used to decode the per MB flags in MB_MODE_INFO */
 
   // Probability Tree used to code Segment number
-  vp9_prob mb_segment_tree_probs[MB_FEATURE_TREE_PROBS];
-  vp9_prob mb_segment_mispred_tree_probs[MAX_MB_SEGMENTS];
+  vp9_prob mb_segment_tree_probs[MB_SEG_TREE_PROBS];
 
   // Segment features
   signed char segment_feature_data[MAX_MB_SEGMENTS][SEG_LVL_MAX];
@@ -920,6 +922,18 @@
     foreach_predicted_block_in_plane(xd, bsize, plane, visit, arg);
   }
 }
+static int raster_block_offset(MACROBLOCKD *xd, BLOCK_SIZE_TYPE bsize,
+                               int plane, int block) {
+  const int bw = b_width_log2(bsize) - xd->plane[plane].subsampling_x;
+  const int stride = 4 << bw;
+  const int y = 4 * (block >> bw), x = 4 * (block & ((1 << bw) - 1));
+  return y * stride + x;
+}
+static int16_t* raster_block_offset_int16(MACROBLOCKD *xd,
+                                         BLOCK_SIZE_TYPE bsize,
+                                         int plane, int block, int16_t *base) {
+  return base + raster_block_offset(xd, bsize, plane, block);
+}
 
 #if CONFIG_CODE_ZEROGROUP
 static int get_zpc_used(TX_SIZE tx_size) {
diff --git a/vp9/common/vp9_entropy.c b/vp9/common/vp9_entropy.c
index a5437d8..16ef14f 100644
--- a/vp9/common/vp9_entropy.c
+++ b/vp9/common/vp9_entropy.c
@@ -12,7 +12,6 @@
 #include <stdio.h>
 
 #include "vp9/common/vp9_entropy.h"
-#include "string.h"
 #include "vp9/common/vp9_blockd.h"
 #include "vp9/common/vp9_onyxc_int.h"
 #include "vp9/common/vp9_entropymode.h"
diff --git a/vp9/common/vp9_entropy.h b/vp9/common/vp9_entropy.h
index 123b5e2..07b07a7 100644
--- a/vp9/common/vp9_entropy.h
+++ b/vp9/common/vp9_entropy.h
@@ -223,6 +223,39 @@
 
 #endif  // CONFIG_CODE_ZEROGROUP
 
+static INLINE const int* get_scan_4x4(TX_TYPE tx_type) {
+  switch (tx_type) {
+    case ADST_DCT:
+      return vp9_row_scan_4x4;
+    case DCT_ADST:
+      return vp9_col_scan_4x4;
+    default:
+      return vp9_default_zig_zag1d_4x4;
+  }
+}
+
+static INLINE const int* get_scan_8x8(TX_TYPE tx_type) {
+  switch (tx_type) {
+    case ADST_DCT:
+      return vp9_row_scan_8x8;
+    case DCT_ADST:
+      return vp9_col_scan_8x8;
+    default:
+      return vp9_default_zig_zag1d_8x8;
+  }
+}
+
+static INLINE const int* get_scan_16x16(TX_TYPE tx_type) {
+  switch (tx_type) {
+    case ADST_DCT:
+      return vp9_row_scan_16x16;
+    case DCT_ADST:
+      return vp9_col_scan_16x16;
+    default:
+      return vp9_default_zig_zag1d_16x16;
+  }
+}
+
 #include "vp9/common/vp9_coefupdateprobs.h"
 
 #endif  // VP9_COMMON_VP9_ENTROPY_H_
diff --git a/vp9/common/vp9_entropymode.c b/vp9/common/vp9_entropymode.c
index 9cb1d2b..ff5abcc 100644
--- a/vp9/common/vp9_entropymode.c
+++ b/vp9/common/vp9_entropymode.c
@@ -96,9 +96,9 @@
 } sumvfref_t;
 
 int vp9_mv_cont(const int_mv *l, const int_mv *a) {
-  int lez = (l->as_int == 0);
-  int aez = (a->as_int == 0);
-  int lea = (l->as_int == a->as_int);
+  const int lez = (l->as_int == 0);
+  const int aez = (a->as_int == 0);
+  const int lea = (l->as_int == a->as_int);
 
   if (lea && lez)
     return SUBMVREF_LEFT_ABOVE_ZED;
@@ -323,30 +323,26 @@
 struct vp9_token vp9_partition_encodings[PARTITION_TYPES];
 
 void vp9_init_mbmode_probs(VP9_COMMON *x) {
-  unsigned int bct [VP9_YMODES] [2];      /* num Ymodes > num UV modes */
+  unsigned int bct[VP9_YMODES][2];  // num Ymodes > num UV modes
+  int i;
 
   vp9_tree_probs_from_distribution(vp9_ymode_tree, x->fc.ymode_prob,
                                    bct, y_mode_cts, 0);
   vp9_tree_probs_from_distribution(vp9_sb_ymode_tree, x->fc.sb_ymode_prob,
                                    bct, y_mode_cts, 0);
-  {
-    int i;
-    for (i = 0; i < 8; i++) {
-      vp9_tree_probs_from_distribution(vp9_kf_ymode_tree, x->kf_ymode_prob[i],
-                                       bct, kf_y_mode_cts[i], 0);
-      vp9_tree_probs_from_distribution(vp9_sb_kf_ymode_tree,
-                                       x->sb_kf_ymode_prob[i], bct,
-                                       kf_y_mode_cts[i], 0);
-    }
+  for (i = 0; i < 8; i++) {
+    vp9_tree_probs_from_distribution(vp9_kf_ymode_tree, x->kf_ymode_prob[i],
+                                     bct, kf_y_mode_cts[i], 0);
+    vp9_tree_probs_from_distribution(vp9_sb_kf_ymode_tree,
+                                     x->sb_kf_ymode_prob[i], bct,
+                                     kf_y_mode_cts[i], 0);
   }
-  {
-    int i;
-    for (i = 0; i < VP9_YMODES; i++) {
-      vp9_tree_probs_from_distribution(vp9_uv_mode_tree, x->kf_uv_mode_prob[i],
-                                       bct, kf_uv_mode_cts[i], 0);
-      vp9_tree_probs_from_distribution(vp9_uv_mode_tree, x->fc.uv_mode_prob[i],
-                                       bct, uv_mode_cts[i], 0);
-    }
+
+  for (i = 0; i < VP9_YMODES; i++) {
+    vp9_tree_probs_from_distribution(vp9_uv_mode_tree, x->kf_uv_mode_prob[i],
+                                     bct, kf_uv_mode_cts[i], 0);
+    vp9_tree_probs_from_distribution(vp9_uv_mode_tree, x->fc.uv_mode_prob[i],
+                                     bct, uv_mode_cts[i], 0);
   }
 
   vp9_tree_probs_from_distribution(vp9_i8x8_mode_tree, x->fc.i8x8_mode_prob,
@@ -482,9 +478,7 @@
 void vp9_accum_mv_refs(VP9_COMMON *pc,
                        MB_PREDICTION_MODE m,
                        const int context) {
-  unsigned int (*mv_ref_ct)[4][2];
-
-  mv_ref_ct = pc->fc.mv_ref_ct;
+  unsigned int (*mv_ref_ct)[4][2] = pc->fc.mv_ref_ct;
 
   if (m == ZEROMV) {
     ++mv_ref_ct[context][0][0];
@@ -512,12 +506,8 @@
 #define MVREF_MAX_UPDATE_FACTOR 128
 void vp9_adapt_mode_context(VP9_COMMON *pc) {
   int i, j;
-  unsigned int (*mv_ref_ct)[4][2];
-  int (*mode_context)[4];
-
-  mode_context = pc->fc.vp9_mode_contexts;
-
-  mv_ref_ct = pc->fc.mv_ref_ct;
+  unsigned int (*mv_ref_ct)[4][2] = pc->fc.mv_ref_ct;
+  int (*mode_context)[4] = pc->fc.vp9_mode_contexts;
 
   for (j = 0; j < INTER_MODE_CONTEXTS; j++) {
     for (i = 0; i < 4; i++) {
@@ -578,93 +568,102 @@
 // #define MODE_COUNT_TESTING
 void vp9_adapt_mode_probs(VP9_COMMON *cm) {
   int i;
+  FRAME_CONTEXT *fc = &cm->fc;
 #ifdef MODE_COUNT_TESTING
   int t;
 
   printf("static const unsigned int\nymode_counts"
          "[VP9_YMODES] = {\n");
-  for (t = 0; t < VP9_YMODES; ++t) printf("%d, ", cm->fc.ymode_counts[t]);
+  for (t = 0; t < VP9_YMODES; ++t)
+    printf("%d, ", fc->ymode_counts[t]);
   printf("};\n");
   printf("static const unsigned int\nuv_mode_counts"
          "[VP9_YMODES] [VP9_UV_MODES] = {\n");
   for (i = 0; i < VP9_YMODES; ++i) {
     printf("  {");
-    for (t = 0; t < VP9_UV_MODES; ++t) printf("%d, ", cm->fc.uv_mode_counts[i][t]);
+    for (t = 0; t < VP9_UV_MODES; ++t)
+      printf("%d, ", fc->uv_mode_counts[i][t]);
     printf("},\n");
   }
   printf("};\n");
   printf("static const unsigned int\nbmode_counts"
          "[VP9_NKF_BINTRAMODES] = {\n");
   for (t = 0; t < VP9_NKF_BINTRAMODES; ++t)
-    printf("%d, ", cm->fc.bmode_counts[t]);
+    printf("%d, ", fc->bmode_counts[t]);
   printf("};\n");
   printf("static const unsigned int\ni8x8_mode_counts"
          "[VP9_I8X8_MODES] = {\n");
-  for (t = 0; t < VP9_I8X8_MODES; ++t) printf("%d, ", cm->fc.i8x8_mode_counts[t]);
+  for (t = 0; t < VP9_I8X8_MODES; ++t)
+    printf("%d, ", fc->i8x8_mode_counts[t]);
   printf("};\n");
   printf("static const unsigned int\nsub_mv_ref_counts"
          "[SUBMVREF_COUNT] [VP9_SUBMVREFS] = {\n");
   for (i = 0; i < SUBMVREF_COUNT; ++i) {
     printf("  {");
-    for (t = 0; t < VP9_SUBMVREFS; ++t) printf("%d, ", cm->fc.sub_mv_ref_counts[i][t]);
+    for (t = 0; t < VP9_SUBMVREFS; ++t)
+      printf("%d, ", fc->sub_mv_ref_counts[i][t]);
     printf("},\n");
   }
   printf("};\n");
   printf("static const unsigned int\nmbsplit_counts"
          "[VP9_NUMMBSPLITS] = {\n");
-  for (t = 0; t < VP9_NUMMBSPLITS; ++t) printf("%d, ", cm->fc.mbsplit_counts[t]);
+  for (t = 0; t < VP9_NUMMBSPLITS; ++t)
+    printf("%d, ", fc->mbsplit_counts[t]);
   printf("};\n");
 #if CONFIG_COMP_INTERINTRA_PRED
   printf("static const unsigned int\ninterintra_counts"
          "[2] = {\n");
-  for (t = 0; t < 2; ++t) printf("%d, ", cm->fc.interintra_counts[t]);
+  for (t = 0; t < 2; ++t)
+    printf("%d, ", fc->interintra_counts[t]);
   printf("};\n");
 #endif
 #endif
 
   update_mode_probs(VP9_YMODES, vp9_ymode_tree,
-                    cm->fc.ymode_counts, cm->fc.pre_ymode_prob,
-                    cm->fc.ymode_prob, 0);
+                    fc->ymode_counts, fc->pre_ymode_prob,
+                    fc->ymode_prob, 0);
   update_mode_probs(VP9_I32X32_MODES, vp9_sb_ymode_tree,
-                    cm->fc.sb_ymode_counts, cm->fc.pre_sb_ymode_prob,
-                    cm->fc.sb_ymode_prob, 0);
-  for (i = 0; i < VP9_YMODES; ++i) {
+                    fc->sb_ymode_counts, fc->pre_sb_ymode_prob,
+                    fc->sb_ymode_prob, 0);
+
+  for (i = 0; i < VP9_YMODES; ++i)
     update_mode_probs(VP9_UV_MODES, vp9_uv_mode_tree,
-                      cm->fc.uv_mode_counts[i], cm->fc.pre_uv_mode_prob[i],
-                      cm->fc.uv_mode_prob[i], 0);
-  }
+                      fc->uv_mode_counts[i], fc->pre_uv_mode_prob[i],
+                      fc->uv_mode_prob[i], 0);
+
   update_mode_probs(VP9_NKF_BINTRAMODES, vp9_bmode_tree,
-                    cm->fc.bmode_counts, cm->fc.pre_bmode_prob,
-                    cm->fc.bmode_prob, 0);
+                    fc->bmode_counts, fc->pre_bmode_prob,
+                    fc->bmode_prob, 0);
   update_mode_probs(VP9_I8X8_MODES,
-                    vp9_i8x8_mode_tree, cm->fc.i8x8_mode_counts,
-                    cm->fc.pre_i8x8_mode_prob, cm->fc.i8x8_mode_prob, 0);
-  for (i = 0; i < SUBMVREF_COUNT; ++i) {
+                    vp9_i8x8_mode_tree, fc->i8x8_mode_counts,
+                    fc->pre_i8x8_mode_prob, fc->i8x8_mode_prob, 0);
+
+  for (i = 0; i < SUBMVREF_COUNT; ++i)
     update_mode_probs(VP9_SUBMVREFS,
-                      vp9_sub_mv_ref_tree, cm->fc.sub_mv_ref_counts[i],
-                      cm->fc.pre_sub_mv_ref_prob[i], cm->fc.sub_mv_ref_prob[i],
+                      vp9_sub_mv_ref_tree, fc->sub_mv_ref_counts[i],
+                      fc->pre_sub_mv_ref_prob[i], fc->sub_mv_ref_prob[i],
                       LEFT4X4);
-  }
+
   update_mode_probs(VP9_NUMMBSPLITS, vp9_mbsplit_tree,
-                    cm->fc.mbsplit_counts, cm->fc.pre_mbsplit_prob,
-                    cm->fc.mbsplit_prob, 0);
+                    fc->mbsplit_counts, fc->pre_mbsplit_prob,
+                    fc->mbsplit_prob, 0);
 #if CONFIG_COMP_INTERINTRA_PRED
   if (cm->use_interintra) {
     int factor, interintra_prob, count;
 
-    interintra_prob = get_binary_prob(cm->fc.interintra_counts[0],
-                                      cm->fc.interintra_counts[1]);
-    count = cm->fc.interintra_counts[0] + cm->fc.interintra_counts[1];
+    interintra_prob = get_binary_prob(fc->interintra_counts[0],
+                                      fc->interintra_counts[1]);
+    count = fc->interintra_counts[0] + fc->interintra_counts[1];
     count = count > MODE_COUNT_SAT ? MODE_COUNT_SAT : count;
     factor = (MODE_MAX_UPDATE_FACTOR * count / MODE_COUNT_SAT);
-    cm->fc.interintra_prob = weighted_prob(cm->fc.pre_interintra_prob,
-                                           interintra_prob, factor);
+    fc->interintra_prob = weighted_prob(fc->pre_interintra_prob,
+                                        interintra_prob, factor);
   }
 #endif
   for (i = 0; i < PARTITION_PLANES; i++)
     update_mode_probs(PARTITION_TYPES, vp9_partition_tree,
-                      cm->fc.partition_counts[i], cm->fc.pre_partition_prob[i],
-                      cm->fc.partition_prob[i], 0);
+                      fc->partition_counts[i], fc->pre_partition_prob[i],
+                      fc->partition_prob[i], 0);
 }
 
 static void set_default_lf_deltas(MACROBLOCKD *xd) {
@@ -691,7 +690,7 @@
   if (cm->last_frame_seg_map)
     vpx_memset(cm->last_frame_seg_map, 0, (cm->mb_rows * cm->mb_cols));
 
-  /* reset the mode ref deltas for loop filter */
+  // Reset the mode ref deltas for loop filter
   vpx_memset(xd->last_ref_lf_deltas, 0, sizeof(xd->last_ref_lf_deltas));
   vpx_memset(xd->last_mode_lf_deltas, 0, sizeof(xd->last_mode_lf_deltas));
   set_default_lf_deltas(xd);
@@ -701,14 +700,14 @@
   vp9_default_bmode_probs(cm->fc.bmode_prob);
   vp9_kf_default_bmode_probs(cm->kf_bmode_prob);
   vp9_init_mv_probs(cm);
+
   // To force update of the sharpness
   cm->last_sharpness_level = -1;
 
   vp9_init_mode_contexts(cm);
 
-  for (i = 0; i < NUM_FRAME_CONTEXTS; i++) {
+  for (i = 0; i < NUM_FRAME_CONTEXTS; i++)
     vpx_memcpy(&cm->frame_contexts[i], &cm->fc, sizeof(cm->fc));
-  }
 
   vpx_memset(cm->prev_mip, 0,
              (cm->mb_cols + 1) * (cm->mb_rows + 1)* sizeof(MODE_INFO));
diff --git a/vp9/common/vp9_loopfilter.h b/vp9/common/vp9_loopfilter.h
index 3b81146..81745e4 100644
--- a/vp9/common/vp9_loopfilter.h
+++ b/vp9/common/vp9_loopfilter.h
@@ -36,7 +36,7 @@
                   lim[MAX_LOOP_FILTER + 1][SIMD_WIDTH]);
   DECLARE_ALIGNED(SIMD_WIDTH, unsigned char,
                   hev_thr[4][SIMD_WIDTH]);
-  unsigned char lvl[4][4][4];
+  unsigned char lvl[MAX_MB_SEGMENTS][4][4];
   unsigned char mode_lf_lut[MB_MODE_COUNT];
 } loop_filter_info_n;
 
diff --git a/vp9/common/vp9_onyx.h b/vp9/common/vp9_onyx.h
index 422f388..b85b889 100644
--- a/vp9/common/vp9_onyx.h
+++ b/vp9/common/vp9_onyx.h
@@ -21,6 +21,9 @@
 #include "vpx/vp8cx.h"
 #include "vpx_scale/yv12config.h"
 #include "vp9/common/vp9_ppflags.h"
+
+#define MAX_MB_SEGMENTS 8
+
   typedef int *VP9_PTR;
 
   /* Create/destroy static data structures. */
@@ -225,8 +228,9 @@
 
   int vp9_set_roimap(VP9_PTR comp, unsigned char *map,
                      unsigned int rows, unsigned int cols,
-                     int delta_q[4], int delta_lf[4],
-                     unsigned int threshold[4]);
+                     int delta_q[MAX_MB_SEGMENTS],
+                     int delta_lf[MAX_MB_SEGMENTS],
+                     unsigned int threshold[MAX_MB_SEGMENTS]);
 
   int vp9_set_active_map(VP9_PTR comp, unsigned char *map,
                          unsigned int rows, unsigned int cols);
diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h
index f9d02e3..dc734b8 100644
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -362,6 +362,10 @@
 }
 
 static int get_token_alloc(int mb_rows, int mb_cols) {
+#if CONFIG_CODE_ZEROGROUP
+  return mb_rows * mb_cols * (24 * 16 * 2);
+#else
   return mb_rows * mb_cols * (24 * 16 + 4);
+#endif
 }
 #endif  // VP9_COMMON_VP9_ONYXC_INT_H_
diff --git a/vp9/common/vp9_pred_common.c b/vp9/common/vp9_pred_common.c
index 5810491..6376bcd 100644
--- a/vp9/common/vp9_pred_common.c
+++ b/vp9/common/vp9_pred_common.c
@@ -23,83 +23,72 @@
                                    const MACROBLOCKD *const xd,
                                    PRED_ID pred_id) {
   int pred_context;
-  MODE_INFO *m = xd->mode_info_context;
-
+  const MODE_INFO *const mi = xd->mode_info_context;
+  const MODE_INFO *const above_mi = mi - cm->mode_info_stride;
+  const MODE_INFO *const left_mi = mi - 1;
   // Note:
   // The mode info data structure has a one element border above and to the
   // left of the entries correpsonding to real macroblocks.
   // The prediction flags in these dummy entries are initialised to 0.
   switch (pred_id) {
     case PRED_SEG_ID:
-      pred_context = (m - cm->mode_info_stride)->mbmi.seg_id_predicted;
+      pred_context = above_mi->mbmi.seg_id_predicted;
       if (xd->left_available)
-        pred_context += (m - 1)->mbmi.seg_id_predicted;
+        pred_context += left_mi->mbmi.seg_id_predicted;
       break;
 
     case PRED_REF:
-      pred_context = (m - cm->mode_info_stride)->mbmi.ref_predicted;
+      pred_context = above_mi->mbmi.ref_predicted;
       if (xd->left_available)
-        pred_context += (m - 1)->mbmi.ref_predicted;
+        pred_context += left_mi->mbmi.ref_predicted;
       break;
 
     case PRED_COMP:
-      // Context based on use of comp pred flag by neighbours
-      // pred_context =
-      //   ((m - 1)->mbmi.second_ref_frame > INTRA_FRAME) +
-      //    ((m - cm->mode_info_stride)->mbmi.second_ref_frame > INTRA_FRAME);
-
-      // Context based on mode and reference frame
-      // if ( m->mbmi.ref_frame == LAST_FRAME )
-      //    pred_context = 0 + (m->mbmi.mode != ZEROMV);
-      // else if ( m->mbmi.ref_frame == GOLDEN_FRAME )
-      //    pred_context = 2 + (m->mbmi.mode != ZEROMV);
-      // else
-      //    pred_context = 4 + (m->mbmi.mode != ZEROMV);
-
-      if (m->mbmi.ref_frame == LAST_FRAME)
+      if (mi->mbmi.ref_frame == LAST_FRAME)
         pred_context = 0;
       else
         pred_context = 1;
-
       break;
 
     case PRED_MBSKIP:
-      pred_context = (m - cm->mode_info_stride)->mbmi.mb_skip_coeff;
+      pred_context = above_mi->mbmi.mb_skip_coeff;
       if (xd->left_available)
-        pred_context += (m - 1)->mbmi.mb_skip_coeff;
+        pred_context += left_mi->mbmi.mb_skip_coeff;
       break;
 
-    case PRED_SWITCHABLE_INTERP:
-      {
-        int left_in_image = xd->left_available && (m - 1)->mbmi.mb_in_image;
-        int above_in_image = (m - cm->mode_info_stride)->mbmi.mb_in_image;
-        int left_mode = (m - 1)->mbmi.mode;
-        int above_mode = (m - cm->mode_info_stride)->mbmi.mode;
-        int left_interp, above_interp;
-        if (left_in_image && left_mode >= NEARESTMV && left_mode <= SPLITMV)
-          left_interp = vp9_switchable_interp_map[(m - 1)->mbmi.interp_filter];
-        else
-          left_interp = VP9_SWITCHABLE_FILTERS;
-        assert(left_interp != -1);
-        if (above_in_image && above_mode >= NEARESTMV && above_mode <= SPLITMV)
-          above_interp = vp9_switchable_interp_map[
-              (m - cm->mode_info_stride)->mbmi.interp_filter];
-        else
-          above_interp = VP9_SWITCHABLE_FILTERS;
-        assert(above_interp != -1);
+    case PRED_SWITCHABLE_INTERP: {
+      // left
+      const int left_in_image = xd->left_available && left_mi->mbmi.mb_in_image;
+      const int left_mv_pred = left_mi->mbmi.mode >= NEARESTMV &&
+                               left_mi->mbmi.mode <= SPLITMV;
+      const int left_interp = left_in_image && left_mv_pred ?
+                    vp9_switchable_interp_map[left_mi->mbmi.interp_filter] :
+                    VP9_SWITCHABLE_FILTERS;
 
-        if (left_interp == above_interp)
-          pred_context = left_interp;
-        else if (left_interp == VP9_SWITCHABLE_FILTERS &&
-                 above_interp != VP9_SWITCHABLE_FILTERS)
-          pred_context = above_interp;
-        else if (left_interp != VP9_SWITCHABLE_FILTERS &&
-                 above_interp == VP9_SWITCHABLE_FILTERS)
-          pred_context = left_interp;
-        else
-          pred_context = VP9_SWITCHABLE_FILTERS;
-      }
+      // above
+      const int above_in_image = above_mi->mbmi.mb_in_image;
+      const int above_mv_pred = above_mi->mbmi.mode >= NEARESTMV &&
+                                above_mi->mbmi.mode <= SPLITMV;
+      const int above_interp = above_in_image && above_mv_pred ?
+                    vp9_switchable_interp_map[above_mi->mbmi.interp_filter] :
+                    VP9_SWITCHABLE_FILTERS;
+
+      assert(left_interp != -1);
+      assert(above_interp != -1);
+
+      if (left_interp == above_interp)
+        pred_context = left_interp;
+      else if (left_interp == VP9_SWITCHABLE_FILTERS &&
+               above_interp != VP9_SWITCHABLE_FILTERS)
+         pred_context = above_interp;
+      else if (left_interp != VP9_SWITCHABLE_FILTERS &&
+               above_interp == VP9_SWITCHABLE_FILTERS)
+        pred_context = left_interp;
+      else
+        pred_context = VP9_SWITCHABLE_FILTERS;
+
       break;
+    }
 
     default:
       pred_context = 0;  // *** add error trap code.
diff --git a/vp9/common/vp9_reconinter.c b/vp9/common/vp9_reconinter.c
index 80eb2c6..c2e0f2f 100644
--- a/vp9/common/vp9_reconinter.c
+++ b/vp9/common/vp9_reconinter.c
@@ -447,14 +447,10 @@
   vp9_build_inter_predictors_sbuv(xd, mb_row, mb_col, bsize);
 
 #if CONFIG_COMP_INTERINTRA_PRED
-  if (xd->mode_info_context->mbmi.second_ref_frame == INTRA_FRAME) {
-    if (bsize == BLOCK_SIZE_SB32X32)
-      vp9_build_interintra_32x32_predictors_sb(xd, y, u, v,
-                                               y_stride, uv_stride);
-    else
-      vp9_build_interintra_64x64_predictors_sb(xd, y, u, v,
-                                               y_stride, uv_stride);
-  }
+  if (xd->mode_info_context->mbmi.second_ref_frame == INTRA_FRAME)
+    vp9_build_interintra_predictors(xd, y, u, v,
+                                    y_stride, uv_stride,
+                                    bsize);
 #endif
 }
 
diff --git a/vp9/common/vp9_reconintra.c b/vp9/common/vp9_reconintra.c
index 1d93dc5..4e786b0 100644
--- a/vp9/common/vp9_reconintra.c
+++ b/vp9/common/vp9_reconintra.c
@@ -410,7 +410,7 @@
                                int interstride,
                                uint8_t *intrapred,
                                int intrastride,
-                               int size) {
+                               int bw, int bh) {
   // TODO(debargha): Explore different ways of combining predictors
   //                 or designing the tables below
   static const int scale_bits = 8;
@@ -428,6 +428,7 @@
      68,  68,  68,  67,  67,  67,  67,  67,
   };
 
+  int size = MAX(bw, bh);
   int size_scale = (size >= 64 ? 1:
                     size == 32 ? 2 :
                     size == 16 ? 4 :
@@ -435,8 +436,8 @@
   int i, j;
   switch (mode) {
     case V_PRED:
-      for (i = 0; i < size; ++i) {
-        for (j = 0; j < size; ++j) {
+      for (i = 0; i < bh; ++i) {
+        for (j = 0; j < bw; ++j) {
           int k = i * interstride + j;
           int scale = weights1d[i * size_scale];
           interpred[k] =
@@ -448,8 +449,8 @@
       break;
 
     case H_PRED:
-      for (i = 0; i < size; ++i) {
-        for (j = 0; j < size; ++j) {
+      for (i = 0; i < bh; ++i) {
+        for (j = 0; j < bw; ++j) {
           int k = i * interstride + j;
           int scale = weights1d[j * size_scale];
           interpred[k] =
@@ -462,8 +463,8 @@
 
     case D63_PRED:
     case D117_PRED:
-      for (i = 0; i < size; ++i) {
-        for (j = 0; j < size; ++j) {
+      for (i = 0; i < bh; ++i) {
+        for (j = 0; j < bw; ++j) {
           int k = i * interstride + j;
           int scale = (weights1d[i * size_scale] * 3 +
                        weights1d[j * size_scale]) >> 2;
@@ -477,8 +478,8 @@
 
     case D27_PRED:
     case D153_PRED:
-      for (i = 0; i < size; ++i) {
-        for (j = 0; j < size; ++j) {
+      for (i = 0; i < bh; ++i) {
+        for (j = 0; j < bw; ++j) {
           int k = i * interstride + j;
           int scale = (weights1d[j * size_scale] * 3 +
                        weights1d[i * size_scale]) >> 2;
@@ -491,8 +492,8 @@
       break;
 
     case D135_PRED:
-      for (i = 0; i < size; ++i) {
-        for (j = 0; j < size; ++j) {
+      for (i = 0; i < bh; ++i) {
+        for (j = 0; j < bw; ++j) {
           int k = i * interstride + j;
           int scale = weights1d[(i < j ? i : j) * size_scale];
           interpred[k] =
@@ -504,8 +505,8 @@
       break;
 
     case D45_PRED:
-      for (i = 0; i < size; ++i) {
-        for (j = 0; j < size; ++j) {
+      for (i = 0; i < bh; ++i) {
+        for (j = 0; j < bw; ++j) {
           int k = i * interstride + j;
           int scale = (weights1d[i * size_scale] +
                        weights1d[j * size_scale]) >> 1;
@@ -521,8 +522,8 @@
     case DC_PRED:
     default:
       // simple average
-      for (i = 0; i < size; ++i) {
-        for (j = 0; j < size; ++j) {
+      for (i = 0; i < bh; ++i) {
+        for (j = 0; j < bw; ++j) {
           int k = i * interstride + j;
           interpred[k] = (interpred[k] + intrapred[i * intrastride + j]) >> 1;
         }
@@ -531,137 +532,55 @@
   }
 }
 
-void vp9_build_interintra_16x16_predictors_mb(MACROBLOCKD *xd,
+void vp9_build_interintra_predictors(MACROBLOCKD *xd,
                                               uint8_t *ypred,
                                               uint8_t *upred,
                                               uint8_t *vpred,
-                                              int ystride, int uvstride) {
-  vp9_build_interintra_16x16_predictors_mby(xd, ypred, ystride);
-  vp9_build_interintra_16x16_predictors_mbuv(xd, upred, vpred, uvstride);
+                                              int ystride, int uvstride,
+                                              BLOCK_SIZE_TYPE bsize) {
+  vp9_build_interintra_predictors_sby(xd, ypred, ystride, bsize);
+  vp9_build_interintra_predictors_sbuv(xd, upred, vpred, uvstride, bsize);
 }
 
-void vp9_build_interintra_16x16_predictors_mby(MACROBLOCKD *xd,
+void vp9_build_interintra_predictors_sby(MACROBLOCKD *xd,
                                                uint8_t *ypred,
-                                               int ystride) {
-  uint8_t intrapredictor[256];
-  vp9_build_intra_predictors(
-      xd->plane[0].dst.buf, xd->plane[0].dst.stride,
-      intrapredictor, 16,
-      xd->mode_info_context->mbmi.interintra_mode, 16, 16,
-      xd->up_available, xd->left_available, xd->right_available);
-  combine_interintra(xd->mode_info_context->mbmi.interintra_mode,
-                     ypred, ystride, intrapredictor, 16, 16);
-}
-
-void vp9_build_interintra_16x16_predictors_mbuv(MACROBLOCKD *xd,
-                                                uint8_t *upred,
-                                                uint8_t *vpred,
-                                                int uvstride) {
-  uint8_t uintrapredictor[64];
-  uint8_t vintrapredictor[64];
-  vp9_build_intra_predictors(
-      xd->plane[1].dst.buf, xd->plane[1].dst.stride,
-      uintrapredictor, 8,
-      xd->mode_info_context->mbmi.interintra_uv_mode, 8, 8,
-      xd->up_available, xd->left_available, xd->right_available);
-  vp9_build_intra_predictors(
-      xd->plane[2].dst.buf, xd->plane[1].dst.stride,
-      vintrapredictor, 8,
-      xd->mode_info_context->mbmi.interintra_uv_mode, 8, 8,
-      xd->up_available, xd->left_available, xd->right_available);
-  combine_interintra(xd->mode_info_context->mbmi.interintra_uv_mode,
-                     upred, uvstride, uintrapredictor, 8, 8);
-  combine_interintra(xd->mode_info_context->mbmi.interintra_uv_mode,
-                     vpred, uvstride, vintrapredictor, 8, 8);
-}
-
-void vp9_build_interintra_32x32_predictors_sby(MACROBLOCKD *xd,
-                                               uint8_t *ypred,
-                                               int ystride) {
-  uint8_t intrapredictor[1024];
-  vp9_build_intra_predictors(
-      xd->plane[0].dst.buf, xd->plane[0].dst.stride,
-      intrapredictor, 32,
-      xd->mode_info_context->mbmi.interintra_mode, 32, 32,
-      xd->up_available, xd->left_available, xd->right_available);
-  combine_interintra(xd->mode_info_context->mbmi.interintra_mode,
-                     ypred, ystride, intrapredictor, 32, 32);
-}
-
-void vp9_build_interintra_32x32_predictors_sbuv(MACROBLOCKD *xd,
-                                                uint8_t *upred,
-                                                uint8_t *vpred,
-                                                int uvstride) {
-  uint8_t uintrapredictor[256];
-  uint8_t vintrapredictor[256];
-  vp9_build_intra_predictors(
-      xd->plane[1].dst.buf, xd->plane[1].dst.stride,
-      uintrapredictor, 16,
-      xd->mode_info_context->mbmi.interintra_uv_mode, 16, 16,
-      xd->up_available, xd->left_available, xd->right_available);
-  vp9_build_intra_predictors(
-      xd->plane[2].dst.buf, xd->plane[1].dst.stride,
-      vintrapredictor, 16,
-      xd->mode_info_context->mbmi.interintra_uv_mode, 16, 16,
-      xd->up_available, xd->left_available, xd->right_available);
-  combine_interintra(xd->mode_info_context->mbmi.interintra_uv_mode,
-                     upred, uvstride, uintrapredictor, 16, 16);
-  combine_interintra(xd->mode_info_context->mbmi.interintra_uv_mode,
-                     vpred, uvstride, vintrapredictor, 16, 16);
-}
-
-void vp9_build_interintra_32x32_predictors_sb(MACROBLOCKD *xd,
-                                              uint8_t *ypred,
-                                              uint8_t *upred,
-                                              uint8_t *vpred,
-                                              int ystride,
-                                              int uvstride) {
-  vp9_build_interintra_32x32_predictors_sby(xd, ypred, ystride);
-  vp9_build_interintra_32x32_predictors_sbuv(xd, upred, vpred, uvstride);
-}
-
-void vp9_build_interintra_64x64_predictors_sby(MACROBLOCKD *xd,
-                                               uint8_t *ypred,
-                                               int ystride) {
+                                               int ystride,
+                                               BLOCK_SIZE_TYPE bsize) {
+  int bwl = mb_width_log2(bsize),  bw = 16 << bwl;
+  int bhl = mb_height_log2(bsize), bh = 16 << bhl;
   uint8_t intrapredictor[4096];
-  const int mode = xd->mode_info_context->mbmi.interintra_mode;
-  vp9_build_intra_predictors(xd->plane[0].dst.buf, xd->plane[0].dst.stride,
-                             intrapredictor, 64, mode, 64, 64,
-                             xd->up_available, xd->left_available,
-                             xd->right_available);
+  vp9_build_intra_predictors(
+      xd->plane[0].dst.buf, xd->plane[0].dst.stride,
+      intrapredictor, bw,
+      xd->mode_info_context->mbmi.interintra_mode, bw, bh,
+      xd->up_available, xd->left_available, xd->right_available);
   combine_interintra(xd->mode_info_context->mbmi.interintra_mode,
-                     ypred, ystride, intrapredictor, 64, 64);
+                     ypred, ystride, intrapredictor, bw, bw, bh);
 }
 
-void vp9_build_interintra_64x64_predictors_sbuv(MACROBLOCKD *xd,
+void vp9_build_interintra_predictors_sbuv(MACROBLOCKD *xd,
                                                 uint8_t *upred,
                                                 uint8_t *vpred,
-                                                int uvstride) {
+                                                int uvstride,
+                                                BLOCK_SIZE_TYPE bsize) {
+  int bwl = mb_width_log2(bsize),  bw = 8 << bwl;
+  int bhl = mb_height_log2(bsize), bh = 8 << bhl;
   uint8_t uintrapredictor[1024];
   uint8_t vintrapredictor[1024];
-  const int mode = xd->mode_info_context->mbmi.interintra_uv_mode;
-  vp9_build_intra_predictors(xd->plane[1].dst.buf, xd->plane[1].dst.stride,
-                             uintrapredictor, 32, mode, 32, 32,
-                             xd->up_available, xd->left_available,
-                             xd->right_available);
-  vp9_build_intra_predictors(xd->plane[2].dst.buf, xd->plane[1].dst.stride,
-                             vintrapredictor, 32, mode, 32, 32,
-                             xd->up_available, xd->left_available,
-                             xd->right_available);
+  vp9_build_intra_predictors(
+      xd->plane[1].dst.buf, xd->plane[1].dst.stride,
+      uintrapredictor, bw,
+      xd->mode_info_context->mbmi.interintra_uv_mode, bw, bh,
+      xd->up_available, xd->left_available, xd->right_available);
+  vp9_build_intra_predictors(
+      xd->plane[2].dst.buf, xd->plane[1].dst.stride,
+      vintrapredictor, bw,
+      xd->mode_info_context->mbmi.interintra_uv_mode, bw, bh,
+      xd->up_available, xd->left_available, xd->right_available);
   combine_interintra(xd->mode_info_context->mbmi.interintra_uv_mode,
-                     upred, uvstride, uintrapredictor, 32, 32);
+                     upred, uvstride, uintrapredictor, bw, bw, bh);
   combine_interintra(xd->mode_info_context->mbmi.interintra_uv_mode,
-                     vpred, uvstride, vintrapredictor, 32, 32);
-}
-
-void vp9_build_interintra_64x64_predictors_sb(MACROBLOCKD *xd,
-                                              uint8_t *ypred,
-                                              uint8_t *upred,
-                                              uint8_t *vpred,
-                                              int ystride,
-                                              int uvstride) {
-  vp9_build_interintra_64x64_predictors_sby(xd, ypred, ystride);
-  vp9_build_interintra_64x64_predictors_sbuv(xd, upred, vpred, uvstride);
+                     vpred, uvstride, vintrapredictor, bw, bw, bh);
 }
 #endif  // CONFIG_COMP_INTERINTRA_PRED
 
diff --git a/vp9/common/vp9_reconintra.h b/vp9/common/vp9_reconintra.h
index 1e0cfa4..e943596 100644
--- a/vp9/common/vp9_reconintra.h
+++ b/vp9/common/vp9_reconintra.h
@@ -21,35 +21,24 @@
 B_PREDICTION_MODE vp9_find_bpred_context(MACROBLOCKD *xd, BLOCKD *x);
 
 #if CONFIG_COMP_INTERINTRA_PRED
-void vp9_build_interintra_16x16_predictors_mb(MACROBLOCKD *xd,
-                                              uint8_t *ypred,
-                                              uint8_t *upred,
-                                              uint8_t *vpred,
-                                              int ystride,
-                                              int uvstride);
+void vp9_build_interintra_predictors(MACROBLOCKD *xd,
+                                     uint8_t *ypred,
+                                     uint8_t *upred,
+                                     uint8_t *vpred,
+                                     int ystride,
+                                     int uvstride,
+                                     BLOCK_SIZE_TYPE bsize);
 
-void vp9_build_interintra_16x16_predictors_mby(MACROBLOCKD *xd,
-                                               uint8_t *ypred,
-                                               int ystride);
+void vp9_build_interintra_predictors_sby(MACROBLOCKD *xd,
+                                         uint8_t *ypred,
+                                         int ystride,
+                                         BLOCK_SIZE_TYPE bsize);
 
-void vp9_build_interintra_16x16_predictors_mbuv(MACROBLOCKD *xd,
-                                                uint8_t *upred,
-                                                uint8_t *vpred,
-                                                int uvstride);
+void vp9_build_interintra_predictors_sbuv(MACROBLOCKD *xd,
+                                          uint8_t *upred,
+                                          uint8_t *vpred,
+                                          int uvstride,
+                                          BLOCK_SIZE_TYPE bsize);
 #endif  // CONFIG_COMP_INTERINTRA_PRED
 
-void vp9_build_interintra_32x32_predictors_sb(MACROBLOCKD *xd,
-                                              uint8_t *ypred,
-                                              uint8_t *upred,
-                                              uint8_t *vpred,
-                                              int ystride,
-                                              int uvstride);
-
-void vp9_build_interintra_64x64_predictors_sb(MACROBLOCKD *xd,
-                                              uint8_t *ypred,
-                                              uint8_t *upred,
-                                              uint8_t *vpred,
-                                              int ystride,
-                                              int uvstride);
-
 #endif  // VP9_COMMON_VP9_RECONINTRA_H_
diff --git a/vp9/common/vp9_rtcd_defs.sh b/vp9/common/vp9_rtcd_defs.sh
index ecca21a..61a2de4 100644
--- a/vp9/common/vp9_rtcd_defs.sh
+++ b/vp9/common/vp9_rtcd_defs.sh
@@ -561,12 +561,6 @@
 specialize vp9_block_error mmx sse2
 vp9_block_error_sse2=vp9_block_error_xmm
 
-prototype void vp9_subtract_b "struct block *be, struct blockd *bd, int pitch"
-# TODO(jingning): The prototype function in c has been changed to remove
-# the use of predictor buffer in MACROBLOCKD. Need to modify the mmx and sse2
-# versions accordingly.
-specialize vp9_subtract_b
-
 #
 # Structured Similarity (SSIM)
 #
diff --git a/vp9/common/vp9_seg_common.c b/vp9/common/vp9_seg_common.c
index df67cff..4c913e2 100644
--- a/vp9/common/vp9_seg_common.c
+++ b/vp9/common/vp9_seg_common.c
@@ -85,4 +85,26 @@
          (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
diff --git a/vp9/common/vp9_seg_common.h b/vp9/common/vp9_seg_common.h
index 243ff88..4550dd1 100644
--- a/vp9/common/vp9_seg_common.h
+++ b/vp9/common/vp9_seg_common.h
@@ -55,5 +55,9 @@
                      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_
 
diff --git a/vp9/decoder/vp9_decodemv.c b/vp9/decoder/vp9_decodemv.c
index c6b11d0..5352a08 100644
--- a/vp9/decoder/vp9_decodemv.c
+++ b/vp9/decoder/vp9_decodemv.c
@@ -75,23 +75,22 @@
 
 static int read_mb_segid(vp9_reader *r, MACROBLOCKD *xd) {
   const vp9_prob *const p = xd->mb_segment_tree_probs;
-  return vp9_read(r, p[0]) ? 2 + vp9_read(r, p[2])
-                           :     vp9_read(r, p[1]);
-}
+  int ret_val;
 
-// This function reads the current macro block's segnent id from the bitstream
-// It should only be called if a segment map update is indicated.
-static int read_mb_segid_except(vp9_reader *r,
-                                VP9_COMMON *cm, MACROBLOCKD *xd,
-                                int mb_row, int mb_col) {
-  const BLOCK_SIZE_TYPE sb_type = xd->mode_info_context->mbmi.sb_type;
-  const int pred_seg_id = vp9_get_pred_mb_segid(cm, sb_type, mb_row, mb_col);
-  const vp9_prob *const p = xd->mb_segment_tree_probs;
-  const vp9_prob prob = xd->mb_segment_mispred_tree_probs[pred_seg_id];
-
-  return vp9_read(r, prob)
-             ? 2 + (pred_seg_id  < 2 ? vp9_read(r, p[2]) : (pred_seg_id == 2))
-             :     (pred_seg_id >= 2 ? vp9_read(r, p[1]) : (pred_seg_id == 0));
+  if (vp9_read(r, p[0])) {
+    if (vp9_read(r, p[4])) {
+      ret_val = 6 + vp9_read(r, p[6]);
+    } else {
+      ret_val = 4 + vp9_read(r, p[5]);
+    }
+  } else {
+    if (vp9_read(r, p[1])) {
+      ret_val = 2 + vp9_read(r, p[3]);
+    } else {
+      ret_val = vp9_read(r, p[2]);
+    }
+  }
+  return ret_val;
 }
 
 static void set_segment_id(VP9_COMMON *cm, MB_MODE_INFO *mbmi,
@@ -116,6 +115,17 @@
   }
 }
 
+static TX_SIZE select_txfm_size(VP9_COMMON *cm, vp9_reader *r,
+                                int allow_16x16, int allow_32x32) {
+  TX_SIZE txfm_size = vp9_read(r, cm->prob_tx[0]);  // TX_4X4 or >TX_4X4
+  if (txfm_size != TX_4X4 && allow_16x16) {
+    txfm_size += vp9_read(r, cm->prob_tx[1]);       // TX_8X8 or >TX_8X8
+    if (txfm_size != TX_8X8 && allow_32x32)
+      txfm_size += vp9_read(r, cm->prob_tx[2]);     // TX_16X16 or >TX_16X16
+  }
+  return txfm_size;
+}
+
 extern const int vp9_i8x8_block[4];
 static void kfread_modes(VP9D_COMP *pbi, MODE_INFO *m,
                          int mb_row, int mb_col,
@@ -174,15 +184,11 @@
   }
 
   if (cm->txfm_mode == TX_MODE_SELECT &&
-      m->mbmi.mb_skip_coeff == 0 &&
+      !m->mbmi.mb_skip_coeff &&
       m->mbmi.mode <= I8X8_PRED) {
-    // FIXME(rbultje) code ternary symbol once all experiments are merged
-    m->mbmi.txfm_size = vp9_read(r, cm->prob_tx[0]);
-    if (m->mbmi.txfm_size != TX_4X4 && m->mbmi.mode != I8X8_PRED) {
-      m->mbmi.txfm_size += vp9_read(r, cm->prob_tx[1]);
-      if (m->mbmi.txfm_size != TX_8X8 && m->mbmi.sb_type >= BLOCK_SIZE_SB32X32)
-        m->mbmi.txfm_size += vp9_read(r, cm->prob_tx[2]);
-    }
+    const int allow_16x16 = m->mbmi.mode != I8X8_PRED;
+    const int allow_32x32 = m->mbmi.sb_type >= BLOCK_SIZE_SB32X32;
+    m->mbmi.txfm_size = select_txfm_size(cm, r, allow_16x16, allow_32x32);
   } else if (cm->txfm_mode >= ALLOW_32X32 &&
              m->mbmi.sb_type >= BLOCK_SIZE_SB32X32) {
     m->mbmi.txfm_size = TX_32X32;
@@ -195,6 +201,7 @@
   }
 }
 
+
 static int read_nmv_component(vp9_reader *r,
                               int rv,
                               const nmv_component *mvcomp) {
@@ -543,7 +550,7 @@
       // then use the predicted value, otherwise decode it explicitly
       segment_id = pred_flag ? vp9_get_pred_mb_segid(cm, mbmi->sb_type,
                                                      mb_row, mb_col)
-                             : read_mb_segid_except(r, cm, xd, mb_row, mb_col);
+                             : read_mb_segid(r, xd);
     } else {
       segment_id = read_mb_segid(r, xd);  // Normal unpredicted coding mode
     }
@@ -981,14 +988,9 @@
       ((mbmi->ref_frame == INTRA_FRAME && mbmi->mode <= I8X8_PRED) ||
        (mbmi->ref_frame != INTRA_FRAME && !(mbmi->mode == SPLITMV &&
                            mbmi->partitioning == PARTITIONING_4X4)))) {
-    // FIXME(rbultje) code ternary symbol once all experiments are merged
-    mbmi->txfm_size = vp9_read(r, cm->prob_tx[0]);
-    if (mbmi->txfm_size != TX_4X4 && mbmi->mode != I8X8_PRED &&
-        mbmi->mode != SPLITMV) {
-      mbmi->txfm_size += vp9_read(r, cm->prob_tx[1]);
-      if (mbmi->sb_type >= BLOCK_SIZE_SB32X32 && mbmi->txfm_size != TX_8X8)
-        mbmi->txfm_size += vp9_read(r, cm->prob_tx[2]);
-    }
+    const int allow_16x16 = mbmi->mode != I8X8_PRED && mbmi->mode != SPLITMV;
+    const int allow_32x32 = mbmi->sb_type >= BLOCK_SIZE_SB32X32;
+    mbmi->txfm_size = select_txfm_size(cm, r, allow_16x16, allow_32x32);
   } else if (mbmi->sb_type >= BLOCK_SIZE_SB32X32 &&
              cm->txfm_mode >= ALLOW_32X32) {
     mbmi->txfm_size = TX_32X32;
diff --git a/vp9/decoder/vp9_decodframe.c b/vp9/decoder/vp9_decodframe.c
index fab26f1..864eb82 100644
--- a/vp9/decoder/vp9_decodframe.c
+++ b/vp9/decoder/vp9_decodframe.c
@@ -37,8 +37,6 @@
 #include <assert.h>
 #include <stdio.h>
 
-#define COEFCOUNT_TESTING
-
 // #define DEC_DEBUG
 #ifdef DEC_DEBUG
 int dec_debug = 0;
@@ -58,11 +56,20 @@
   return start + len > start && start + len <= end;
 }
 
-static TXFM_MODE read_txfm_mode(vp9_reader *r) {
-  TXFM_MODE mode = vp9_read_literal(r, 2);
-  if (mode == ALLOW_32X32)
-    mode += vp9_read_bit(r);
-  return mode;
+static void setup_txfm_mode(VP9_COMMON *pc, int lossless, vp9_reader *r) {
+  if (lossless) {
+    pc->txfm_mode = ONLY_4X4;
+  } else {
+    pc->txfm_mode = vp9_read_literal(r, 2);
+    if (pc->txfm_mode == ALLOW_32X32)
+      pc->txfm_mode += vp9_read_bit(r);
+
+    if (pc->txfm_mode == TX_MODE_SELECT) {
+      pc->prob_tx[0] = vp9_read_prob(r);
+      pc->prob_tx[1] = vp9_read_prob(r);
+      pc->prob_tx[2] = vp9_read_prob(r);
+    }
+  }
 }
 
 static int get_unsigned_bits(unsigned int num_values) {
@@ -165,10 +172,11 @@
   VP9_COMMON *const pc = &pbi->common;
 
   for (q = 0; q < QINDEX_RANGE; q++) {
+    // DC value
     pc->y_dequant[q][0] = (int16_t)vp9_dc_quant(q, pc->y_dc_delta_q);
     pc->uv_dequant[q][0] = (int16_t)vp9_dc_uv_quant(q, pc->uv_dc_delta_q);
 
-    /* all the ac values =; */
+    // AC values
     for (i = 1; i < 16; i++) {
       const int rc = vp9_default_zig_zag1d_4x4[i];
 
@@ -305,7 +313,7 @@
 
 static INLINE void dequant_add_y(MACROBLOCKD *xd, TX_TYPE tx_type, int idx) {
   BLOCKD *const b = &xd->block[idx];
-  struct mb_plane *const y = &xd->plane[0];
+  struct macroblockd_plane *const y = &xd->plane[0];
   if (tx_type != DCT_DCT) {
     vp9_dequant_iht_add_c(tx_type,
                           BLOCK_OFFSET(y->qcoeff, idx, 16),
@@ -771,11 +779,6 @@
   return old_value != *dq;
 }
 
-#ifdef PACKET_TESTING
-#include <stdio.h>
-FILE *vpxlog = 0;
-#endif
-
 static void set_offsets(VP9D_COMP *pbi, BLOCK_SIZE_TYPE bsize,
                         int mb_row, int mb_col) {
   const int bh = 1 << mb_height_log2(bsize);
@@ -959,7 +962,6 @@
   xd->frame_type = pc->frame_type;
   xd->mode_info_context->mbmi.mode = DC_PRED;
   xd->mode_info_stride = pc->mode_info_stride;
-  xd->corrupted = 0;
 }
 
 #if CONFIG_CODE_ZEROGROUP
@@ -1001,7 +1003,7 @@
 static void read_zpc_probs(VP9_COMMON *cm,
                            vp9_reader* bc) {
   read_zpc_probs_common(cm, bc, TX_4X4);
-  if (cm->txfm_mode != ONLY_4X4)
+  if (cm->txfm_mode > ONLY_4X4)
     read_zpc_probs_common(cm, bc, TX_8X8);
   if (cm->txfm_mode > ALLOW_8X8)
     read_zpc_probs_common(cm, bc, TX_16X16);
@@ -1055,7 +1057,7 @@
 
   read_coef_probs_common(pbi, r, fc->coef_probs_4x4, TX_4X4);
 
-  if (mode != ONLY_4X4)
+  if (mode > ONLY_4X4)
     read_coef_probs_common(pbi, r, fc->coef_probs_8x8, TX_8X8);
 
   if (mode > ALLOW_8X8)
@@ -1091,59 +1093,53 @@
 
   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) {
-    // Segmentation map update
-    xd->update_mb_segmentation_map = vp9_read_bit(r);
-    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)
-                                                       : MAX_PROB;
+  if (!xd->segmentation_enabled)
+    return;
 
-      pc->temporal_update = vp9_read_bit(r);
-      if (pc->temporal_update) {
-        const vp9_prob *p = xd->mb_segment_tree_probs;
-        vp9_prob *mispred_p = xd->mb_segment_mispred_tree_probs;
+  // 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_SEG_TREE_PROBS; i++)
+      xd->mb_segment_tree_probs[i] = vp9_read_bit(r) ? vp9_read_prob(r)
+                                                     : MAX_PROB;
 
-        const int c0 =        p[0]  *        p[1];
-        const int c1 =        p[0]  * (256 - p[1]);
-        const int c2 = (256 - p[0]) *        p[2];
-        const int c3 = (256 - p[0]) * (256 - p[2]);
-
-        mispred_p[0] = get_binary_prob(c1, c2 + c3);
-        mispred_p[1] = get_binary_prob(c0, c2 + c3);
-        mispred_p[2] = get_binary_prob(c0 + c1, c3);
-        mispred_p[3] = get_binary_prob(c0 + c1, c2);
-
-        for (i = 0; i < PREDICTION_PROBS; i++)
-          pc->segment_pred_probs[i] = vp9_read_bit(r) ? vp9_read_prob(r)
-                                                      : MAX_PROB;
-      } else {
-        for (i = 0; i < PREDICTION_PROBS; i++)
-          pc->segment_pred_probs[i] = MAX_PROB;
-      }
+    pc->temporal_update = vp9_read_bit(r);
+    if (pc->temporal_update) {
+      for (i = 0; i < PREDICTION_PROBS; i++)
+        pc->segment_pred_probs[i] = vp9_read_bit(r) ? vp9_read_prob(r)
+                                                    : MAX_PROB;
+    } else {
+      for (i = 0; i < PREDICTION_PROBS; i++)
+        pc->segment_pred_probs[i] = MAX_PROB;
     }
+  }
 
-    // Segmentation data update
-    xd->update_mb_segmentation_data = vp9_read_bit(r);
-    if (xd->update_mb_segmentation_data) {
-      xd->mb_segment_abs_delta = vp9_read_bit(r);
+  // Segmentation data update
+  xd->update_mb_segmentation_data = vp9_read_bit(r);
+  if (xd->update_mb_segmentation_data) {
+    xd->mb_segment_abs_delta = vp9_read_bit(r);
 
-      vp9_clearall_segfeatures(xd);
+    vp9_clearall_segfeatures(xd);
 
-      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);
-          if (feature_enabled) {
-            vp9_enable_segfeature(xd, i, j);
-            data = decode_unsigned_max(r, vp9_seg_feature_data_max(j));
-            if (vp9_is_segfeature_signed(j))
-              data = vp9_read_and_apply_sign(r, data);
-          }
-          vp9_set_segdata(xd, i, j, data);
+    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);
+        if (feature_enabled) {
+          vp9_enable_segfeature(xd, i, j);
+          data = decode_unsigned_max(r, vp9_seg_feature_data_max(j));
+          if (vp9_is_segfeature_signed(j))
+            data = vp9_read_and_apply_sign(r, data);
         }
+        vp9_set_segdata(xd, i, j, data);
       }
     }
   }
@@ -1180,8 +1176,8 @@
   // Read in loop filter deltas applied at the MB level based on mode or ref
   // frame.
   xd->mode_ref_lf_delta_update = 0;
-  xd->mode_ref_lf_delta_enabled = vp9_read_bit(r);
 
+  xd->mode_ref_lf_delta_enabled = vp9_read_bit(r);
   if (xd->mode_ref_lf_delta_enabled) {
     xd->mode_ref_lf_delta_update = vp9_read_bit(r);
     if (xd->mode_ref_lf_delta_update) {
@@ -1217,6 +1213,11 @@
   mb_init_dequantizer(pbi, &pbi->mb);  // MB level dequantizer setup
 }
 
+static INTERPOLATIONFILTERTYPE read_mcomp_filter_type(vp9_reader *r) {
+  return vp9_read_bit(r) ? SWITCHABLE
+                         : vp9_read_literal(r, 2);
+}
+
 static const uint8_t *read_frame_size(VP9_COMMON *const pc, const uint8_t *data,
                                       const uint8_t *data_end,
                                       int *width, int *height) {
@@ -1423,12 +1424,11 @@
   const uint8_t *data = pbi->source;
   const uint8_t *data_end = data + pbi->source_sz;
   size_t first_partition_size = 0;
-  int i, corrupt_tokens = 0;
-
-  // printf("Decoding frame %d\n", pc->current_video_frame);
+  YV12_BUFFER_CONFIG *new_fb = &pc->yv12_fb[pc->new_fb_idx];
+  int i;
 
   xd->corrupted = 0;  // start with no corruption of current frame
-  pc->yv12_fb[pc->new_fb_idx].corrupted = 0;
+  new_fb->corrupted = 0;
 
   if (data_end - data < 3) {
     vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME, "Truncated packet");
@@ -1471,8 +1471,7 @@
   init_frame(pbi);
 
   // Reset the frame pointers to the current frame size
-  vp8_yv12_realloc_frame_buffer(&pc->yv12_fb[pc->new_fb_idx],
-                                pc->width, pc->height,
+  vp8_yv12_realloc_frame_buffer(new_fb, pc->width, pc->height,
                                 VP9BORDERINPIXELS);
 
   if (vp9_reader_init(&header_bc, data, first_partition_size))
@@ -1487,8 +1486,7 @@
 
   setup_loopfilter(pc, xd, &header_bc);
 
-  // Dummy read for now
-  vp9_read_literal(&header_bc, 2);
+  vp9_read_literal(&header_bc, 2);  // unused
 
   setup_quantization(pbi, &header_bc);
 
@@ -1510,14 +1508,8 @@
 
     pc->ref_frame_sign_bias[GOLDEN_FRAME] = vp9_read_bit(&header_bc);
     pc->ref_frame_sign_bias[ALTREF_FRAME] = vp9_read_bit(&header_bc);
-
-    // Is high precision mv allowed
     xd->allow_high_precision_mv = vp9_read_bit(&header_bc);
-
-    // Read the type of subpel filter to use
-    pc->mcomp_filter_type = vp9_read_bit(&header_bc)
-                                ? SWITCHABLE
-                                : vp9_read_literal(&header_bc, 2);
+    pc->mcomp_filter_type = read_mcomp_filter_type(&header_bc);
 
 #if CONFIG_COMP_INTERINTRA_PRED
     pc->use_interintra = vp9_read_bit(&header_bc);
@@ -1545,6 +1537,7 @@
     pc->refresh_entropy_probs = 0;
     pc->frame_parallel_decoding_mode = 1;
   }
+
   pc->frame_context_idx = vp9_read_literal(&header_bc, NUM_FRAME_CONTEXTS_LG2);
   vpx_memcpy(&pc->fc, &pc->frame_contexts[pc->frame_context_idx],
              sizeof(pc->fc));
@@ -1553,12 +1546,7 @@
 
   setup_pred_probs(pc, &header_bc);
 
-  pc->txfm_mode = xd->lossless ? ONLY_4X4 : read_txfm_mode(&header_bc);
-  if (pc->txfm_mode == TX_MODE_SELECT) {
-    pc->prob_tx[0] = vp9_read_prob(&header_bc);
-    pc->prob_tx[1] = vp9_read_prob(&header_bc);
-    pc->prob_tx[2] = vp9_read_prob(&header_bc);
-  }
+  setup_txfm_mode(pc, xd->lossless, &header_bc);
 
   // Read inter mode probability context updates
   if (pc->frame_type != KEY_FRAME) {
@@ -1569,32 +1557,21 @@
           pc->fc.vp9_mode_contexts[i][j] = vp9_read_prob(&header_bc);
   }
 #if CONFIG_MODELCOEFPROB
-  if (pc->frame_type == KEY_FRAME) {
+  if (pc->frame_type == KEY_FRAME)
     vp9_default_coef_probs(pc);
-  }
 #endif
 
-  if (0) {
-    FILE *z = fopen("decodestats.stt", "a");
-    fprintf(z, "%6d F:%d,R:%d,Q:%d\n",
-            pc->current_video_frame,
-            pc->frame_type,
-            pbi->refresh_frame_flags,
-            pc->base_qindex);
-    fclose(z);
-  }
-
   update_frame_context(pbi);
 
   read_coef_probs(pbi, &header_bc);
 #if CONFIG_CODE_ZEROGROUP
-  read_zpc_probs(&pbi->common, &header_bc);
+  read_zpc_probs(pc, &header_bc);
 #endif
 
   // Initialize xd pointers. Any reference should do for xd->pre, so use 0.
   setup_pre_planes(xd, &pc->yv12_fb[pc->active_ref_idx[0]], NULL,
                    0, 0, NULL, NULL);
-  setup_dst_planes(xd, &pc->yv12_fb[pc->new_fb_idx], 0, 0);
+  setup_dst_planes(xd, new_fb, 0, 0);
 
   // Create the segmentation map structure and set to 0
   if (!pc->last_frame_seg_map)
@@ -1602,7 +1579,7 @@
                     vpx_calloc((pc->mb_rows * pc->mb_cols), 1));
 
   // set up frame new frame for intra coded blocks
-  vp9_setup_intra_recon(&pc->yv12_fb[pc->new_fb_idx]);
+  vp9_setup_intra_recon(new_fb);
 
   vp9_setup_block_dptrs(xd);
   vp9_build_block_doffsets(xd);
@@ -1617,56 +1594,45 @@
   vp9_decode_mode_mvs_init(pbi, &header_bc);
 
   decode_tiles(pbi, data, first_partition_size, &header_bc, &residual_bc);
-  corrupt_tokens |= xd->corrupted;
 
-  // keep track of the last coded dimensions
   pc->last_width = pc->width;
   pc->last_height = pc->height;
 
-  // Collect information about decoder corruption.
-  // 1. Check first boolean decoder for errors.
-  // 2. Check the macroblock information
-  pc->yv12_fb[pc->new_fb_idx].corrupted = vp9_reader_has_error(&header_bc) |
-                                          corrupt_tokens;
+  new_fb->corrupted = vp9_reader_has_error(&header_bc) | xd->corrupted;
 
   if (!pbi->decoded_key_frame) {
-    if (pc->frame_type == KEY_FRAME && !pc->yv12_fb[pc->new_fb_idx].corrupted)
+    if (pc->frame_type == KEY_FRAME && !new_fb->corrupted)
       pbi->decoded_key_frame = 1;
     else
-      vpx_internal_error(&pbi->common.error, VPX_CODEC_CORRUPT_FRAME,
+      vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
                          "A stream must start with a complete key frame");
   }
 
+  // Adaptation
   if (!pc->error_resilient_mode && !pc->frame_parallel_decoding_mode) {
     vp9_adapt_coef_probs(pc);
 #if CONFIG_CODE_ZEROGROUP
     vp9_adapt_zpc_probs(pc);
 #endif
-  }
-
-  if (pc->frame_type != KEY_FRAME) {
-    if (!pc->error_resilient_mode && !pc->frame_parallel_decoding_mode) {
+    if (pc->frame_type != KEY_FRAME) {
       vp9_adapt_mode_probs(pc);
       vp9_adapt_nmv_probs(pc, xd->allow_high_precision_mv);
-      vp9_adapt_mode_context(&pbi->common);
+      vp9_adapt_mode_context(pc);
     }
   }
 
+#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));
   }
 
-#ifdef PACKET_TESTING
-  {
-    FILE *f = fopen("decompressor.VP8", "ab");
-    unsigned int size = residual_bc.pos + header_bc.pos + 8;
-    fwrite((void *) &size, 4, 1, f);
-    fwrite((void *) pbi->Source, size, 1, f);
-    fclose(f);
-  }
-#endif
-
   *p_data_end = vp9_reader_find_end(&residual_bc);
   return 0;
 }
diff --git a/vp9/decoder/vp9_detokenize.c b/vp9/decoder/vp9_detokenize.c
index 18ef51a..02ee7c3 100644
--- a/vp9/decoder/vp9_detokenize.c
+++ b/vp9/decoder/vp9_detokenize.c
@@ -165,17 +165,7 @@
     case TX_4X4: {
       tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
           get_tx_type_4x4(xd, block_idx) : DCT_DCT;
-      switch (tx_type) {
-        default:
-          scan = vp9_default_zig_zag1d_4x4;
-          break;
-        case ADST_DCT:
-          scan = vp9_row_scan_4x4;
-          break;
-        case DCT_ADST:
-          scan = vp9_col_scan_4x4;
-          break;
-      }
+      scan = get_scan_4x4(tx_type);
       above_ec = A0[aidx] != 0;
       left_ec = L0[lidx] != 0;
       coef_probs  = fc->coef_probs_4x4;
@@ -194,17 +184,7 @@
       const int y = block_idx - x;
       tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
           get_tx_type_8x8(xd, y + (x >> 1)) : DCT_DCT;
-      switch (tx_type) {
-        default:
-          scan = vp9_default_zig_zag1d_8x8;
-          break;
-        case ADST_DCT:
-          scan = vp9_row_scan_8x8;
-          break;
-        case DCT_ADST:
-          scan = vp9_col_scan_8x8;
-          break;
-      }
+      scan = get_scan_8x8(tx_type);
       coef_probs  = fc->coef_probs_8x8;
       coef_counts = fc->coef_counts_8x8;
       above_ec = (A0[aidx] + A0[aidx + 1]) != 0;
@@ -223,17 +203,7 @@
       const int y = block_idx - x;
       tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
           get_tx_type_16x16(xd, y + (x >> 2)) : DCT_DCT;
-      switch (tx_type) {
-        default:
-          scan = vp9_default_zig_zag1d_16x16;
-          break;
-        case ADST_DCT:
-          scan = vp9_row_scan_16x16;
-          break;
-        case DCT_ADST:
-          scan = vp9_col_scan_16x16;
-          break;
-      }
+      scan = get_scan_16x16(tx_type);
       coef_probs  = fc->coef_probs_16x16;
       coef_counts = fc->coef_counts_16x16;
       if (type == PLANE_TYPE_UV) {
diff --git a/vp9/encoder/vp9_asm_enc_offsets.c b/vp9/encoder/vp9_asm_enc_offsets.c
index 1a770dc..d8e844e 100644
--- a/vp9/encoder/vp9_asm_enc_offsets.c
+++ b/vp9/encoder/vp9_asm_enc_offsets.c
@@ -20,15 +20,6 @@
 BEGIN
 
 /* regular quantize */
-DEFINE(vp9_block_coeff,                         offsetof(BLOCK, coeff));
-DEFINE(vp9_block_zbin,                          offsetof(BLOCK, zbin));
-DEFINE(vp9_block_round,                         offsetof(BLOCK, round));
-DEFINE(vp9_block_quant,                         offsetof(BLOCK, quant));
-DEFINE(vp9_block_quant_fast,                    offsetof(BLOCK, quant_fast));
-DEFINE(vp9_block_zbin_extra,                    offsetof(BLOCK, zbin_extra));
-DEFINE(vp9_block_zrun_zbin_boost,               offsetof(BLOCK, zrun_zbin_boost));
-DEFINE(vp9_block_quant_shift,                   offsetof(BLOCK, quant_shift));
-
 DEFINE(vp9_blockd_dequant,                      offsetof(BLOCKD, dequant));
 
 END
diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c
index 2231621..e80c9cc 100644
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -537,51 +537,54 @@
       case 0:
         vp9_write(bc, 0, xd->mb_segment_tree_probs[0]);
         vp9_write(bc, 0, xd->mb_segment_tree_probs[1]);
+        vp9_write(bc, 0, xd->mb_segment_tree_probs[2]);
         break;
       case 1:
         vp9_write(bc, 0, xd->mb_segment_tree_probs[0]);
-        vp9_write(bc, 1, xd->mb_segment_tree_probs[1]);
+        vp9_write(bc, 0, xd->mb_segment_tree_probs[1]);
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[2]);
         break;
       case 2:
-        vp9_write(bc, 1, xd->mb_segment_tree_probs[0]);
-        vp9_write(bc, 0, xd->mb_segment_tree_probs[2]);
+        vp9_write(bc, 0, xd->mb_segment_tree_probs[0]);
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[1]);
+        vp9_write(bc, 0, xd->mb_segment_tree_probs[3]);
         break;
       case 3:
+        vp9_write(bc, 0, xd->mb_segment_tree_probs[0]);
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[1]);
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[3]);
+        break;
+      case 4:
         vp9_write(bc, 1, xd->mb_segment_tree_probs[0]);
-        vp9_write(bc, 1, xd->mb_segment_tree_probs[2]);
+        vp9_write(bc, 0, xd->mb_segment_tree_probs[4]);
+        vp9_write(bc, 0, xd->mb_segment_tree_probs[5]);
+        break;
+      case 5:
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[0]);
+        vp9_write(bc, 0, xd->mb_segment_tree_probs[4]);
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[5]);
+        break;
+      case 6:
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[0]);
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[4]);
+        vp9_write(bc, 0, xd->mb_segment_tree_probs[6]);
+        break;
+      case 7:
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[0]);
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[4]);
+        vp9_write(bc, 1, xd->mb_segment_tree_probs[6]);
         break;
 
         // TRAP.. This should not happen
       default:
         vp9_write(bc, 0, xd->mb_segment_tree_probs[0]);
         vp9_write(bc, 0, xd->mb_segment_tree_probs[1]);
+        vp9_write(bc, 0, xd->mb_segment_tree_probs[2]);
         break;
     }
   }
 }
 
-static void write_mb_segid_except(VP9_COMMON *cm,
-                                  vp9_writer *bc,
-                                  const MB_MODE_INFO *mi,
-                                  const MACROBLOCKD *xd,
-                                  int mb_row, int mb_col) {
-  // Encode the MB segment id.
-  const int seg_id = mi->segment_id;
-  const BLOCK_SIZE_TYPE sb_type = xd->mode_info_context->mbmi.sb_type;
-  const int pred_seg_id = vp9_get_pred_mb_segid(cm, sb_type, mb_row, mb_col);
-  const vp9_prob *p = xd->mb_segment_tree_probs;
-  const vp9_prob p1 = xd->mb_segment_mispred_tree_probs[pred_seg_id];
-
-  if (xd->segmentation_enabled && xd->update_mb_segmentation_map) {
-    vp9_write(bc, seg_id >= 2, p1);
-    if (pred_seg_id >= 2 && seg_id < 2) {
-      vp9_write(bc, seg_id == 1, p[1]);
-    } else if (pred_seg_id < 2 && seg_id >= 2) {
-      vp9_write(bc, seg_id == 3, p[2]);
-    }
-  }
-}
-
 // This function encodes the reference frame
 static void encode_ref_frame(vp9_writer *const bc,
                              VP9_COMMON *const cm,
@@ -725,7 +728,7 @@
 
       // If the mb segment id wasn't predicted code explicitly
       if (!prediction_flag)
-        write_mb_segid_except(pc, bc, mi, &cpi->mb.e_mbd, mb_row, mb_col);
+        write_mb_segid(bc, mi, &cpi->mb.e_mbd);
     } else {
       // Normal unpredicted coding
       write_mb_segid(bc, mi, &cpi->mb.e_mbd);
@@ -1989,6 +1992,9 @@
   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) {
@@ -1996,7 +2002,7 @@
       vp9_choose_segmap_coding_method(cpi);
       // Send the tree probabilities used to decode unpredicted
       // macro-block segments
-      for (i = 0; i < MB_FEATURE_TREE_PROBS; i++) {
+      for (i = 0; i < MB_SEG_TREE_PROBS; i++) {
         const int prob = xd->mb_segment_tree_probs[i];
         if (prob != 255) {
           vp9_write_bit(&header_bc, 1);
diff --git a/vp9/encoder/vp9_block.h b/vp9/encoder/vp9_block.h
index 965797d..9d8abab 100644
--- a/vp9/encoder/vp9_block.h
+++ b/vp9/encoder/vp9_block.h
@@ -24,33 +24,10 @@
 } search_site;
 
 typedef struct block {
-  // 16 Y blocks, 4 U blocks, 4 V blocks each with 16 entries
-  int16_t *src_diff;
-  int16_t *coeff;
-
-  // 16 Y blocks, 4 U blocks, 4 V blocks each with 16 entries
-  int16_t *quant;
-  int16_t *quant_fast;      // fast quant deprecated for now
-  uint8_t *quant_shift;
-  int16_t *zbin;
-  int16_t *zbin_8x8;
-  int16_t *zbin_16x16;
-  int16_t *zbin_32x32;
-  int16_t *zrun_zbin_boost;
-  int16_t *zrun_zbin_boost_8x8;
-  int16_t *zrun_zbin_boost_16x16;
-  int16_t *zrun_zbin_boost_32x32;
-  int16_t *round;
-
-  // Zbin Over Quant value
-  short zbin_extra;
-
   uint8_t **base_src;
   uint8_t **base_second_src;
   int src;
   int src_stride;
-
-  int skip_block;
 } BLOCK;
 
 typedef struct {
@@ -89,10 +66,25 @@
   unsigned int frames_with_high_error;
 } PICK_MODE_CONTEXT;
 
+struct macroblock_plane {
+  DECLARE_ALIGNED(16, int16_t, src_diff[64*64]);
+  DECLARE_ALIGNED(16, int16_t, coeff[64*64]);
+
+  // Quantizer setings
+  int16_t *quant;
+  uint8_t *quant_shift;
+  int16_t *zbin;
+  int16_t *zrun_zbin_boost;
+  int16_t *round;
+
+  // Zbin Over Quant value
+  int16_t zbin_extra;
+};
+
 typedef struct macroblock MACROBLOCK;
 struct macroblock {
-  DECLARE_ALIGNED(16, int16_t, src_diff[64*64+32*32*2]);
-  DECLARE_ALIGNED(16, int16_t, coeff[64*64+32*32*2]);
+  struct macroblock_plane plane[MAX_MB_PLANE];
+  int skip_block;
   // 16 Y blocks, 4 U blocks, 4 V blocks,
   BLOCK block[24];
 
@@ -151,9 +143,6 @@
 
   int encode_breakout;
 
-  // char * gf_active_ptr;
-  signed char *gf_active_ptr;
-
   unsigned char *active_ptr;
 
   vp9_coeff_count token_costs[TX_SIZE_MAX_SB][BLOCK_TYPES];
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index 1978f19..b1b28c7 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -594,7 +594,7 @@
       mbmi->segment_id = find_seg_id(cm->last_frame_seg_map, bsize,
                                      mb_row, cm->mb_rows, mb_col, cm->mb_cols);
     }
-    assert(mbmi->segment_id <= 3);
+    assert(mbmi->segment_id <= (MAX_MB_SEGMENTS-1));
     vp9_mb_init_quantizer(cpi, x);
 
     if (xd->segmentation_enabled && cpi->seg0_cnt > 0 &&
@@ -1248,8 +1248,6 @@
 
   vp9_setup_block_dptrs(&x->e_mbd);
 
-  vp9_setup_block_ptrs(x);
-
   xd->mode_info_context->mbmi.mode = DC_PRED;
   xd->mode_info_context->mbmi.uv_mode = DC_PRED;
 
@@ -1733,30 +1731,6 @@
 
 }
 
-void vp9_setup_block_ptrs(MACROBLOCK *x) {
-  int r, c;
-  int i;
-
-  for (r = 0; r < 4; r++) {
-    for (c = 0; c < 4; c++)
-      x->block[r * 4 + c].src_diff = x->src_diff + r * 4 * 16 + c * 4;
-  }
-
-  for (r = 0; r < 2; r++) {
-    for (c = 0; c < 2; c++)
-      x->block[16 + r * 2 + c].src_diff = x->src_diff + 256 + r * 4 * 8 + c * 4;
-  }
-
-
-  for (r = 0; r < 2; r++) {
-    for (c = 0; c < 2; c++)
-      x->block[20 + r * 2 + c].src_diff = x->src_diff + 320 + r * 4 * 8 + c * 4;
-  }
-
-  for (i = 0; i < 24; i++)
-    x->block[i].coeff = x->coeff + i * 16;
-}
-
 void vp9_build_block_offsets(MACROBLOCK *x) {
   int block = 0;
   int br, bc;
@@ -1989,12 +1963,13 @@
       vp9_build_inter_predictors_sb(xd, mb_row, mb_col, BLOCK_SIZE_MB16X16);
 #if CONFIG_COMP_INTERINTRA_PRED
       if (xd->mode_info_context->mbmi.second_ref_frame == INTRA_FRAME) {
-        vp9_build_interintra_16x16_predictors_mb(xd,
-                                                 xd->plane[0].dst.buf,
-                                                 xd->plane[1].dst.buf,
-                                                 xd->plane[2].dst.buf,
-                                                 xd->plane[0].dst.stride,
-                                                 xd->plane[1].dst.stride);
+        vp9_build_interintra_predictors(xd,
+                                        xd->plane[0].dst.buf,
+                                        xd->plane[1].dst.buf,
+                                        xd->plane[2].dst.buf,
+                                        xd->plane[0].dst.stride,
+                                        xd->plane[1].dst.stride,
+                                        BLOCK_SIZE_MB16X16);
       }
 #endif
     }
@@ -2100,14 +2075,6 @@
   VP9_COMMON *const cm = &cpi->common;
   MACROBLOCK *const x = &cpi->mb;
   MACROBLOCKD *const xd = &x->e_mbd;
-  const uint8_t *src = x->src.y_buffer;
-  uint8_t *dst = xd->plane[0].dst.buf;
-  const uint8_t *usrc = x->src.u_buffer;
-  uint8_t *udst = xd->plane[1].dst.buf;
-  const uint8_t *vsrc = x->src.v_buffer;
-  uint8_t *vdst = xd->plane[2].dst.buf;
-  int src_y_stride = x->src.y_stride, dst_y_stride = xd->plane[0].dst.stride;
-  int src_uv_stride = x->src.uv_stride, dst_uv_stride = xd->plane[1].dst.stride;
   int n;
   MODE_INFO *mi = x->e_mbd.mode_info_context;
   unsigned int segment_id = mi->mbmi.segment_id;
@@ -2187,10 +2154,7 @@
   }
 
   if (!x->skip) {
-    vp9_subtract_sby_s_c(x->src_diff, src, src_y_stride, dst, dst_y_stride,
-                         bsize);
-    vp9_subtract_sbuv_s_c(x->src_diff, usrc, vsrc, src_uv_stride,
-                          udst, vdst, dst_uv_stride, bsize);
+    vp9_subtract_sb(x, bsize);
 
     switch (xd->mode_info_context->mbmi.txfm_size) {
       case TX_32X32:
diff --git a/vp9/encoder/vp9_encodeframe.h b/vp9/encoder/vp9_encodeframe.h
index 9f13edc..4ace468 100644
--- a/vp9/encoder/vp9_encodeframe.h
+++ b/vp9/encoder/vp9_encodeframe.h
@@ -16,6 +16,4 @@
 
 void vp9_build_block_offsets(struct macroblock *x);
 
-void vp9_setup_block_ptrs(struct macroblock *x);
-
 #endif  // VP9_ENCODER_VP9_ENCODEFRAME_H_
diff --git a/vp9/encoder/vp9_encodeintra.c b/vp9/encoder/vp9_encodeintra.c
index 5c6559b..66d62d9 100644
--- a/vp9/encoder/vp9_encodeintra.c
+++ b/vp9/encoder/vp9_encodeintra.c
@@ -37,7 +37,7 @@
     }
   }
 
-  return vp9_get_mb_ss(x->src_diff);
+  return vp9_get_mb_ss(x->plane[0].src_diff);
 }
 
 static void encode_intra4x4block(MACROBLOCK *x, int ib) {
@@ -45,6 +45,10 @@
   BLOCK *be = &x->block[ib];
   MACROBLOCKD * const xd = &x->e_mbd;
   TX_TYPE tx_type;
+  int16_t* const src_diff =
+      raster_block_offset_int16(xd, BLOCK_SIZE_MB16X16, 0, ib,
+                                x->plane[0].src_diff);
+  int16_t* const coeff = BLOCK_OFFSET(x->plane[0].coeff, ib, 16);
 
   assert(ib < 16);
 
@@ -54,16 +58,18 @@
 
   vp9_intra4x4_predict(&x->e_mbd, b, b->bmi.as_mode.first,
                        *(b->base_dst) + b->dst, b->dst_stride);
-  vp9_subtract_b(be, b, 16);
+  vp9_subtract_block(4, 4, src_diff, 16,
+                     *(be->base_src) + be->src, be->src_stride,
+                     *(b->base_dst) + b->dst, b->dst_stride);
 
   tx_type = get_tx_type_4x4(&x->e_mbd, ib);
   if (tx_type != DCT_DCT) {
-    vp9_short_fht4x4(be->src_diff, be->coeff, 16, tx_type);
+    vp9_short_fht4x4(src_diff, coeff, 16, tx_type);
     vp9_ht_quantize_b_4x4(x, ib, tx_type);
     vp9_short_iht4x4(BLOCK_OFFSET(xd->plane[0].dqcoeff, ib, 16),
                      b->diff, 16, tx_type);
   } else {
-    x->fwd_txm4x4(be->src_diff, be->coeff, 32);
+    x->fwd_txm4x4(src_diff, coeff, 32);
     x->quantize_b_4x4(x, ib, 16);
     vp9_inverse_transform_b_4x4(&x->e_mbd, xd->plane[0].eobs[ib],
                                 BLOCK_OFFSET(xd->plane[0].dqcoeff, ib, 16),
@@ -86,10 +92,7 @@
   TX_SIZE tx_size = xd->mode_info_context->mbmi.txfm_size;
 
   vp9_build_intra_predictors_sby_s(xd, BLOCK_SIZE_MB16X16);
-  vp9_subtract_sby_s_c(x->src_diff,
-                       x->src.y_buffer, x->src.y_stride,
-                       xd->plane[0].dst.buf, xd->plane[0].dst.stride,
-                       BLOCK_SIZE_MB16X16);
+  vp9_subtract_sby(x, BLOCK_SIZE_MB16X16);
 
   switch (tx_size) {
     case TX_16X16:
@@ -123,11 +126,7 @@
   TX_SIZE tx_size = xd->mode_info_context->mbmi.txfm_size;
 
   vp9_build_intra_predictors_sbuv_s(xd, BLOCK_SIZE_MB16X16);
-  vp9_subtract_sbuv_s_c(x->src_diff,
-                        x->src.u_buffer, x->src.v_buffer, x->src.uv_stride,
-                        xd->plane[1].dst.buf, xd->plane[2].dst.buf,
-                        xd->plane[1].dst.stride,
-                        BLOCK_SIZE_MB16X16);
+  vp9_subtract_sbuv(x, BLOCK_SIZE_MB16X16);
 
   switch (tx_size) {
     case TX_4X4:
@@ -153,6 +152,9 @@
   MACROBLOCKD *xd = &x->e_mbd;
   BLOCKD *b = &xd->block[ib];
   BLOCK *be = &x->block[ib];
+  int16_t* const src_diff =
+      raster_block_offset_int16(xd, BLOCK_SIZE_MB16X16, 0, ib,
+                                x->plane[0].src_diff);
   const int iblock[4] = {0, 1, 4, 5};
   int i;
   TX_TYPE tx_type;
@@ -160,40 +162,47 @@
   vp9_intra8x8_predict(xd, b, b->bmi.as_mode.first,
                        *(b->base_dst) + b->dst, b->dst_stride);
   // generate residual blocks
-  vp9_subtract_4b_c(be, b, 16);
+  vp9_subtract_block(8, 8, src_diff, 16,
+                     *(be->base_src) + be->src, be->src_stride,
+                     *(b->base_dst) + b->dst, b->dst_stride);
 
   if (xd->mode_info_context->mbmi.txfm_size == TX_8X8) {
     int idx = (ib & 0x02) ? (ib + 2) : ib;
-    int16_t * const dqcoeff = BLOCK_OFFSET(xd->plane[0].dqcoeff, idx, 16);
+    int16_t* const dqcoeff = BLOCK_OFFSET(xd->plane[0].dqcoeff, idx, 16);
+    int16_t* const coeff = BLOCK_OFFSET(x->plane[0].coeff, idx, 16);
 
     assert(idx < 16);
     tx_type = get_tx_type_8x8(xd, ib);
     if (tx_type != DCT_DCT) {
-      vp9_short_fht8x8(be->src_diff, (x->block + idx)->coeff, 16, tx_type);
+      vp9_short_fht8x8(src_diff, coeff, 16, tx_type);
       x->quantize_b_8x8(x, idx, tx_type, 16);
       vp9_short_iht8x8(dqcoeff, xd->block[ib].diff,
                             16, tx_type);
     } else {
-      x->fwd_txm8x8(be->src_diff, (x->block + idx)->coeff, 32);
+      x->fwd_txm8x8(src_diff, coeff, 32);
       x->quantize_b_8x8(x, idx, DCT_DCT, 16);
       vp9_short_idct8x8(dqcoeff, xd->block[ib].diff, 32);
     }
   } else {
     for (i = 0; i < 4; i++) {
       int idx = ib + iblock[i];
-      int16_t * const dqcoeff = BLOCK_OFFSET(xd->plane[0].dqcoeff, idx, 16);
+      int16_t* const dqcoeff = BLOCK_OFFSET(xd->plane[0].dqcoeff, idx, 16);
+      int16_t* const coeff = BLOCK_OFFSET(x->plane[0].coeff, idx, 16);
+      int16_t* const src_diff =
+          raster_block_offset_int16(xd, BLOCK_SIZE_MB16X16, 0, idx,
+                                    x->plane[0].src_diff);
 
       assert(idx < 16);
       b = &xd->block[ib + iblock[i]];
       be = &x->block[ib + iblock[i]];
       tx_type = get_tx_type_4x4(xd, ib + iblock[i]);
       if (tx_type != DCT_DCT) {
-        vp9_short_fht4x4(be->src_diff, be->coeff, 16, tx_type);
+        vp9_short_fht4x4(src_diff, coeff, 16, tx_type);
         vp9_ht_quantize_b_4x4(x, ib + iblock[i], tx_type);
         vp9_short_iht4x4(dqcoeff, b->diff, 16, tx_type);
       } else if (!(i & 1) &&
                  get_tx_type_4x4(xd, ib + iblock[i] + 1) == DCT_DCT) {
-        x->fwd_txm8x4(be->src_diff, be->coeff, 32);
+        x->fwd_txm8x4(src_diff, coeff, 32);
         x->quantize_b_4x4_pair(x, ib + iblock[i], ib + iblock[i] + 1, 16);
         vp9_inverse_transform_b_4x4(xd, xd->plane[0].eobs[ib + iblock[i]],
                                     dqcoeff, b->diff, 32);
@@ -201,7 +210,7 @@
                                     dqcoeff + 16, (b + 1)->diff, 32);
         i++;
       } else {
-        x->fwd_txm4x4(be->src_diff, be->coeff, 32);
+        x->fwd_txm4x4(src_diff, coeff, 32);
         x->quantize_b_4x4(x, ib + iblock[i], 16);
         vp9_inverse_transform_b_4x4(xd, xd->plane[0].eobs[ib + iblock[i]],
                                     dqcoeff, b->diff, 32);
@@ -229,16 +238,23 @@
   BLOCKD *b = &x->e_mbd.block[ib];
   BLOCK *be = &x->block[ib];
   int16_t * const dqcoeff = MB_SUBBLOCK_FIELD(xd, dqcoeff, ib);
+  int16_t* const coeff = MB_SUBBLOCK_FIELD(x, coeff, ib);
   const int plane = ib < 20 ? 1 : 2;
   const int block = ib < 20 ? ib - 16 : ib - 20;
+  int16_t* const src_diff =
+      raster_block_offset_int16(xd, BLOCK_SIZE_MB16X16, plane, block,
+                                x->plane[plane].src_diff);
 
   assert(ib >= 16 && ib < 24);
   vp9_intra_uv4x4_predict(&x->e_mbd, b, mode,
                           *(b->base_dst) + b->dst, b->dst_stride);
 
-  vp9_subtract_b(be, b, 8);
+  assert(xd->plane[1].subsampling_x == 1);
+  vp9_subtract_block(4, 4, src_diff, 8,
+                     *(be->base_src) + be->src, be->src_stride,
+                     *(b->base_dst) + b->dst, b->dst_stride);
 
-  x->fwd_txm4x4(be->src_diff, be->coeff, 16);
+  x->fwd_txm4x4(src_diff, coeff, 16);
   x->quantize_b_4x4(x, ib, 16);
   vp9_inverse_transform_b_4x4(&x->e_mbd, xd->plane[plane].eobs[block],
                               dqcoeff, b->diff, 16);
diff --git a/vp9/encoder/vp9_encodemb.c b/vp9/encoder/vp9_encodemb.c
index c841c28..d8893b6 100644
--- a/vp9/encoder/vp9_encodemb.c
+++ b/vp9/encoder/vp9_encodemb.c
@@ -20,102 +20,54 @@
 #include "vp9/common/vp9_systemdependent.h"
 #include "vp9_rtcd.h"
 
-void vp9_subtract_b_c(BLOCK *be, BLOCKD *bd, int pitch) {
-  uint8_t *src_ptr = (*(be->base_src) + be->src);
-  int16_t *diff_ptr = be->src_diff;
-  uint8_t *pred_ptr = *(bd->base_dst) + bd->dst;
-  int src_stride = be->src_stride;
-  int dst_stride = bd->dst_stride;
-
+void vp9_subtract_block(int rows, int cols,
+                        int16_t *diff_ptr, int diff_stride,
+                        const uint8_t *src_ptr, int src_stride,
+                        const uint8_t *pred_ptr, int pred_stride) {
   int r, c;
 
-  for (r = 0; r < 4; r++) {
-    for (c = 0; c < 4; c++)
+  for (r = 0; r < rows; r++) {
+    for (c = 0; c < cols; c++)
       diff_ptr[c] = src_ptr[c] - pred_ptr[c];
 
-    diff_ptr += pitch;
-    pred_ptr += dst_stride;
+    diff_ptr += diff_stride;
+    pred_ptr += pred_stride;
     src_ptr  += src_stride;
   }
 }
 
-void vp9_subtract_4b_c(BLOCK *be, BLOCKD *bd, int pitch) {
-  uint8_t *src_ptr = (*(be->base_src) + be->src);
-  int16_t *diff_ptr = be->src_diff;
-  uint8_t *pred_ptr = *(bd->base_dst) + bd->dst;
-  int src_stride = be->src_stride;
-  int dst_stride = bd->dst_stride;
-  int r, c;
 
-  for (r = 0; r < 8; r++) {
-    for (c = 0; c < 8; c++)
-      diff_ptr[c] = src_ptr[c] - pred_ptr[c];
+static void subtract_plane(MACROBLOCK *x, BLOCK_SIZE_TYPE bsize, int plane) {
+  const MACROBLOCKD * const xd = &x->e_mbd;
+  const int bw = 4 << (b_width_log2(bsize) - xd->plane[plane].subsampling_x);
+  const int bh = 4 << (b_height_log2(bsize) - xd->plane[plane].subsampling_y);
+  const uint8_t *src = plane == 0 ? x->src.y_buffer :
+                       plane == 1 ? x->src.u_buffer : x->src.v_buffer;
+  const int src_stride = plane == 0 ? x->src.y_stride : x->src.uv_stride;
 
-    diff_ptr += pitch;
-    pred_ptr += dst_stride;
-    src_ptr  += src_stride;
-  }
+  assert(plane < 3);
+  vp9_subtract_block(bh, bw,
+                     x->plane[plane].src_diff, bw, src, src_stride,
+                     xd->plane[plane].dst.buf, xd->plane[plane].dst.stride);
 }
 
-void vp9_subtract_sby_s_c(int16_t *diff, const uint8_t *src, int src_stride,
-                          const uint8_t *pred, int dst_stride,
-                          BLOCK_SIZE_TYPE bsize) {
-  const int bh = 16 << mb_height_log2(bsize), bw = 16 << mb_width_log2(bsize);
-  int r, c;
-
-  for (r = 0; r < bh; r++) {
-    for (c = 0; c < bw; c++)
-      diff[c] = src[c] - pred[c];
-
-    diff += bw;
-    pred += dst_stride;
-    src  += src_stride;
-  }
+void vp9_subtract_sby(MACROBLOCK *x, BLOCK_SIZE_TYPE bsize) {
+  subtract_plane(x, bsize, 0);
 }
 
-void vp9_subtract_sbuv_s_c(int16_t *diff, const uint8_t *usrc,
-                           const uint8_t *vsrc, int src_stride,
-                           const uint8_t *upred,
-                           const uint8_t *vpred, int dst_stride,
-                           BLOCK_SIZE_TYPE bsize) {
-  const int bhl = mb_height_log2(bsize), bwl = mb_width_log2(bsize);
-  const int uoff = (16 * 16) << (bhl + bwl), voff = (uoff * 5) >> 2;
-  const int bw = 8 << bwl, bh = 8 << bhl;
-  int16_t *udiff = diff + uoff;
-  int16_t *vdiff = diff + voff;
-  int r, c;
+void vp9_subtract_sbuv(MACROBLOCK *x, BLOCK_SIZE_TYPE bsize) {
+  int i;
 
-  for (r = 0; r < bh; r++) {
-    for (c = 0; c < bw; c++)
-      udiff[c] = usrc[c] - upred[c];
-
-    udiff += bw;
-    upred += dst_stride;
-    usrc  += src_stride;
-  }
-
-  for (r = 0; r < bh; r++) {
-    for (c = 0; c < bw; c++)
-      vdiff[c] = vsrc[c] - vpred[c];
-
-    vdiff += bw;
-    vpred += dst_stride;
-    vsrc  += src_stride;
-  }
+  for (i = 1; i < MAX_MB_PLANE; i++)
+    subtract_plane(x, bsize, i);
 }
 
-static void subtract_mb(MACROBLOCK *x) {
-  MACROBLOCKD *xd = &x->e_mbd;
-  vp9_subtract_sby_s_c(x->src_diff, x->src.y_buffer, x->src.y_stride,
-                       xd->plane[0].dst.buf, xd->plane[0].dst.stride,
-                       BLOCK_SIZE_MB16X16);
-  vp9_subtract_sbuv_s_c(x->src_diff, x->src.u_buffer, x->src.v_buffer,
-                        x->src.uv_stride,
-                        xd->plane[1].dst.buf, xd->plane[2].dst.buf,
-                        xd->plane[1].dst.stride,
-                        BLOCK_SIZE_MB16X16);
+void vp9_subtract_sb(MACROBLOCK *x, BLOCK_SIZE_TYPE bsize) {
+  vp9_subtract_sby(x, bsize);
+  vp9_subtract_sbuv(x, bsize);
 }
 
+
 void vp9_transform_sby_32x32(MACROBLOCK *x, BLOCK_SIZE_TYPE bsize) {
   const int bwl = mb_width_log2(bsize) - 1, bw = 1 << bwl;
   const int bh = 1 << (mb_height_log2(bsize) - 1);
@@ -125,8 +77,8 @@
   for (n = 0; n < bw * bh; n++) {
     const int x_idx = n & (bw - 1), y_idx = n >> bwl;
 
-    vp9_short_fdct32x32(x->src_diff + y_idx * stride * 32 + x_idx * 32,
-                        x->coeff + n * 1024, stride * 2);
+    vp9_short_fdct32x32(x->plane[0].src_diff + y_idx * stride * 32 + x_idx * 32,
+                        x->plane[0].coeff + n * 1024, stride * 2);
   }
 }
 
@@ -143,11 +95,12 @@
                                               (y_idx * bstride + x_idx) * 4);
 
     if (tx_type != DCT_DCT) {
-      vp9_short_fht16x16(x->src_diff + y_idx * stride * 16 + x_idx * 16,
-                         x->coeff + n * 256, stride, tx_type);
+      vp9_short_fht16x16(x->plane[0].src_diff +
+                             y_idx * stride * 16 + x_idx * 16,
+                         x->plane[0].coeff + n * 256, stride, tx_type);
     } else {
-      x->fwd_txm16x16(x->src_diff + y_idx * stride * 16 + x_idx * 16,
-                      x->coeff + n * 256, stride * 2);
+      x->fwd_txm16x16(x->plane[0].src_diff + y_idx * stride * 16 + x_idx * 16,
+                      x->plane[0].coeff + n * 256, stride * 2);
     }
   }
 }
@@ -164,11 +117,11 @@
     const TX_TYPE tx_type = get_tx_type_8x8(xd, (y_idx * bstride + x_idx) * 2);
 
     if (tx_type != DCT_DCT) {
-      vp9_short_fht8x8(x->src_diff + y_idx * stride * 8 + x_idx * 8,
-                       x->coeff + n * 64, stride, tx_type);
+      vp9_short_fht8x8(x->plane[0].src_diff + y_idx * stride * 8 + x_idx * 8,
+                       x->plane[0].coeff + n * 64, stride, tx_type);
     } else {
-      x->fwd_txm8x8(x->src_diff + y_idx * stride * 8 + x_idx * 8,
-                    x->coeff + n * 64, stride * 2);
+      x->fwd_txm8x8(x->plane[0].src_diff + y_idx * stride * 8 + x_idx * 8,
+                    x->plane[0].coeff + n * 64, stride * 2);
     }
   }
 }
@@ -185,11 +138,11 @@
     const TX_TYPE tx_type = get_tx_type_4x4(xd, n);
 
     if (tx_type != DCT_DCT) {
-      vp9_short_fht4x4(x->src_diff + y_idx * stride * 4 + x_idx * 4,
-                       x->coeff + n * 16, stride, tx_type);
+      vp9_short_fht4x4(x->plane[0].src_diff + y_idx * stride * 4 + x_idx * 4,
+                       x->plane[0].coeff + n * 16, stride, tx_type);
     } else {
-      x->fwd_txm4x4(x->src_diff + y_idx * stride * 4 + x_idx * 4,
-                    x->coeff + n * 16, stride * 2);
+      x->fwd_txm4x4(x->plane[0].src_diff + y_idx * stride * 4 + x_idx * 4,
+                    x->plane[0].coeff + n * 16, stride * 2);
     }
   }
 }
@@ -197,15 +150,12 @@
 void vp9_transform_sbuv_32x32(MACROBLOCK *x, BLOCK_SIZE_TYPE bsize) {
   assert(bsize == BLOCK_SIZE_SB64X64);
   vp9_clear_system_state();
-  vp9_short_fdct32x32(x->src_diff + 4096,
-                      x->coeff + 4096, 64);
-  vp9_short_fdct32x32(x->src_diff + 4096 + 1024,
-                      x->coeff + 4096 + 1024, 64);
+  vp9_short_fdct32x32(x->plane[1].src_diff, x->plane[1].coeff, 64);
+  vp9_short_fdct32x32(x->plane[2].src_diff, x->plane[2].coeff, 64);
 }
 
 void vp9_transform_sbuv_16x16(MACROBLOCK *x, BLOCK_SIZE_TYPE bsize) {
   const int bwl = mb_width_log2(bsize), bhl = mb_height_log2(bsize);
-  const int uoff = (16 * 16) << (bwl + bhl), voff = (uoff * 5) >> 2;
   const int bw = 1 << (bwl - 1), bh = 1 << (bhl - 1);
   const int stride = 16 << (bwl - 1);
   int n;
@@ -214,16 +164,15 @@
   for (n = 0; n < bw * bh; n++) {
     const int x_idx = n & (bw - 1), y_idx = n >> (bwl - 1);
 
-    x->fwd_txm16x16(x->src_diff + uoff + y_idx * stride * 16 + x_idx * 16,
-                    x->coeff + uoff + n * 256, stride * 2);
-    x->fwd_txm16x16(x->src_diff + voff + y_idx * stride * 16 + x_idx * 16,
-                    x->coeff + voff + n * 256, stride * 2);
+    x->fwd_txm16x16(x->plane[1].src_diff + y_idx * stride * 16 + x_idx * 16,
+                    x->plane[1].coeff + n * 256, stride * 2);
+    x->fwd_txm16x16(x->plane[2].src_diff + y_idx * stride * 16 + x_idx * 16,
+                    x->plane[2].coeff + n * 256, stride * 2);
   }
 }
 
 void vp9_transform_sbuv_8x8(MACROBLOCK *x, BLOCK_SIZE_TYPE bsize) {
   const int bwl = mb_width_log2(bsize) + 1, bhl = mb_height_log2(bsize) + 1;
-  const int uoff = (8 * 8) << (bwl + bhl), voff = (uoff * 5) >> 2;
   const int bw = 1 << (bwl - 1), bh = 1 << (bhl - 1);
   const int stride = 8 << (bwl - 1);
   int n;
@@ -232,16 +181,15 @@
   for (n = 0; n < bw * bh; n++) {
     const int x_idx = n & (bw - 1), y_idx = n >> (bwl - 1);
 
-    x->fwd_txm8x8(x->src_diff + uoff + y_idx * stride * 8 + x_idx * 8,
-                  x->coeff + uoff + n * 64, stride * 2);
-    x->fwd_txm8x8(x->src_diff + voff + y_idx * stride * 8 + x_idx * 8,
-                  x->coeff + voff + n * 64, stride * 2);
+    x->fwd_txm8x8(x->plane[1].src_diff + y_idx * stride * 8 + x_idx * 8,
+                  x->plane[1].coeff + n * 64, stride * 2);
+    x->fwd_txm8x8(x->plane[2].src_diff + y_idx * stride * 8 + x_idx * 8,
+                  x->plane[2].coeff + n * 64, stride * 2);
   }
 }
 
 void vp9_transform_sbuv_4x4(MACROBLOCK *x, BLOCK_SIZE_TYPE bsize) {
   const int bwl = mb_width_log2(bsize) + 2, bhl = mb_height_log2(bsize) + 2;
-  const int uoff = (4 * 4) << (bwl + bhl), voff = (uoff * 5) >> 2;
   const int bw = 1 << (bwl - 1), bh = 1 << (bhl - 1);
   const int stride = 4 << (bwl - 1);
   int n;
@@ -250,10 +198,10 @@
   for (n = 0; n < bw * bh; n++) {
     const int x_idx = n & (bw - 1), y_idx = n >> (bwl - 1);
 
-    x->fwd_txm4x4(x->src_diff + uoff + y_idx * stride * 4 + x_idx * 4,
-                  x->coeff + uoff + n * 16, stride * 2);
-    x->fwd_txm4x4(x->src_diff + voff + y_idx * stride * 4 + x_idx * 4,
-                  x->coeff + voff + n * 16, stride * 2);
+    x->fwd_txm4x4(x->plane[1].src_diff + y_idx * stride * 4 + x_idx * 4,
+                  x->plane[1].coeff + n * 16, stride * 2);
+    x->fwd_txm4x4(x->plane[2].src_diff + y_idx * stride * 4 + x_idx * 4,
+                  x->plane[2].coeff + n * 16, stride * 2);
   }
 }
 
@@ -312,7 +260,8 @@
   vp9_token_state tokens[1025][2];
   unsigned best_index[1025][2];
   const struct plane_block_idx pb_idx = plane_block_idx(y_blocks, ib);
-  const int16_t *coeff_ptr = mb->coeff + ib * 16;
+  const int16_t *coeff_ptr = BLOCK_OFFSET(mb->plane[pb_idx.plane].coeff,
+                                          pb_idx.block, 16);
   int16_t *qcoeff_ptr;
   int16_t *dqcoeff_ptr;
   int eob = xd->plane[pb_idx.plane].eobs[pb_idx.block], final_eob, sz = 0;
@@ -335,13 +284,7 @@
     case TX_4X4: {
       const TX_TYPE tx_type = get_tx_type_4x4(xd, ib);
       default_eob = 16;
-      if (tx_type == DCT_ADST) {
-        scan = vp9_col_scan_4x4;
-      } else if (tx_type == ADST_DCT) {
-        scan = vp9_row_scan_4x4;
-      } else {
-        scan = vp9_default_zig_zag1d_4x4;
-      }
+      scan = get_scan_4x4(tx_type);
       break;
     }
     case TX_8X8: {
@@ -349,13 +292,7 @@
       const int sz = 3 + mb_width_log2(sb_type);
       const int x = ib & ((1 << sz) - 1), y = ib - x;
       const TX_TYPE tx_type = get_tx_type_8x8(xd, y + (x >> 1));
-      if (tx_type == DCT_ADST) {
-        scan = vp9_col_scan_8x8;
-      } else if (tx_type == ADST_DCT) {
-        scan = vp9_row_scan_8x8;
-      } else {
-        scan = vp9_default_zig_zag1d_8x8;
-      }
+      scan = get_scan_8x8(tx_type);
       default_eob = 64;
       break;
     }
@@ -364,13 +301,7 @@
       const int sz = 4 + mb_width_log2(sb_type);
       const int x = ib & ((1 << sz) - 1), y = ib - x;
       const TX_TYPE tx_type = get_tx_type_16x16(xd, y + (x >> 2));
-      if (tx_type == DCT_ADST) {
-        scan = vp9_col_scan_16x16;
-      } else if (tx_type == ADST_DCT) {
-        scan = vp9_row_scan_16x16;
-      } else {
-        scan = vp9_default_zig_zag1d_16x16;
-      }
+      scan = get_scan_16x16(tx_type);
       default_eob = 256;
       break;
     }
@@ -844,7 +775,7 @@
   MACROBLOCKD *const xd = &x->e_mbd;
 
   vp9_build_inter_predictors_sb(xd, mb_row, mb_col, BLOCK_SIZE_MB16X16);
-  subtract_mb(x);
+  vp9_subtract_sb(x, BLOCK_SIZE_MB16X16);
   vp9_fidct_mb(cm, x);
   vp9_recon_sb(xd, BLOCK_SIZE_MB16X16);
 }
@@ -854,9 +785,7 @@
   MACROBLOCKD *xd = &x->e_mbd;
 
   vp9_build_inter_predictors_sby(xd, mb_row, mb_col, BLOCK_SIZE_MB16X16);
-  vp9_subtract_sby_s_c(x->src_diff, x->src.y_buffer, x->src.y_stride,
-                       xd->plane[0].dst.buf, xd->plane[0].dst.stride,
-                       BLOCK_SIZE_MB16X16);
+  vp9_subtract_sby(x, BLOCK_SIZE_MB16X16);
 
   vp9_transform_sby_4x4(x, BLOCK_SIZE_MB16X16);
   vp9_quantize_sby_4x4(x, BLOCK_SIZE_MB16X16);
diff --git a/vp9/encoder/vp9_encodemb.h b/vp9/encoder/vp9_encodemb.h
index 3c0d760..da134a8 100644
--- a/vp9/encoder/vp9_encodemb.h
+++ b/vp9/encoder/vp9_encodemb.h
@@ -56,15 +56,12 @@
 
 void vp9_fidct_mb(VP9_COMMON *const cm, MACROBLOCK *x);
 
-void vp9_subtract_4b_c(BLOCK *be, BLOCKD *bd, int pitch);
-
-void vp9_subtract_sby_s_c(int16_t *diff, const uint8_t *src, int src_stride,
-                          const uint8_t *pred, int dst_stride,
-                          BLOCK_SIZE_TYPE bsize);
-void vp9_subtract_sbuv_s_c(int16_t *diff, const uint8_t *usrc,
-                           const uint8_t *vsrc, int src_stride,
-                           const uint8_t *upred,
-                           const uint8_t *vpred, int dst_stride,
-                           BLOCK_SIZE_TYPE bsize);
+void vp9_subtract_block(int rows, int cols,
+                        int16_t *diff_ptr, int diff_stride,
+                        const uint8_t *src_ptr, int src_stride,
+                        const uint8_t *pred_ptr, int pred_stride);
+void vp9_subtract_sby(MACROBLOCK *x, BLOCK_SIZE_TYPE bsize);
+void vp9_subtract_sbuv(MACROBLOCK *x, BLOCK_SIZE_TYPE bsize);
+void vp9_subtract_sb(MACROBLOCK *xd, BLOCK_SIZE_TYPE bsize);
 
 #endif  // VP9_ENCODER_VP9_ENCODEMB_H_
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index b18dce4..e441107 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -496,8 +496,6 @@
 
   vp9_setup_block_dptrs(&x->e_mbd);
 
-  vp9_setup_block_ptrs(x);
-
   // set up frame new frame for intra coded blocks
   vp9_setup_intra_recon(new_yv12);
   vp9_frame_init_quantizer(cpi);
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index b294870..c2c587e 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -285,6 +285,9 @@
 
   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 @@
     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 @@
     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 @@
   }
 }
 
+#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 @@
   // 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 @@
       // 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 @@
     }
   }
 
-  // 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 @@
         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 @@
   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);
@@ -4132,8 +4204,9 @@
 }
 
 int vp9_set_roimap(VP9_PTR comp, unsigned char *map, unsigned int rows,
-                   unsigned int cols, int delta_q[4], int delta_lf[4],
-                   unsigned int threshold[4]) {
+                   unsigned int cols, int delta_q[MAX_MB_SEGMENTS],
+                   int delta_lf[MAX_MB_SEGMENTS],
+                   unsigned int threshold[MAX_MB_SEGMENTS]) {
   VP9_COMP *cpi = (VP9_COMP *) comp;
   signed char feature_data[SEG_LVL_MAX][MAX_MB_SEGMENTS];
   MACROBLOCKD *xd = &cpi->mb.e_mbd;
@@ -4153,25 +4226,15 @@
   // Activate segmentation.
   vp9_enable_segmentation((VP9_PTR)cpi);
 
-  // Set up the quant segment data
-  feature_data[SEG_LVL_ALT_Q][0] = delta_q[0];
-  feature_data[SEG_LVL_ALT_Q][1] = delta_q[1];
-  feature_data[SEG_LVL_ALT_Q][2] = delta_q[2];
-  feature_data[SEG_LVL_ALT_Q][3] = delta_q[3];
-
-  // Set up the loop segment data s
-  feature_data[SEG_LVL_ALT_LF][0] = delta_lf[0];
-  feature_data[SEG_LVL_ALT_LF][1] = delta_lf[1];
-  feature_data[SEG_LVL_ALT_LF][2] = delta_lf[2];
-  feature_data[SEG_LVL_ALT_LF][3] = delta_lf[3];
-
-  cpi->segment_encode_breakout[0] = threshold[0];
-  cpi->segment_encode_breakout[1] = threshold[1];
-  cpi->segment_encode_breakout[2] = threshold[2];
-  cpi->segment_encode_breakout[3] = threshold[3];
+  // Set up the quan, LF and breakout threshold segment data
+  for (i = 0; i < MAX_MB_SEGMENTS; i++) {
+    feature_data[SEG_LVL_ALT_Q][i] = delta_q[i];
+    feature_data[SEG_LVL_ALT_LF][i] = delta_lf[i];
+    cpi->segment_encode_breakout[i] = threshold[i];
+  }
 
   // Enable the loop and quant changes in the feature mask
-  for (i = 0; i < 4; i++) {
+  for (i = 0; i < MAX_MB_SEGMENTS; i++) {
     if (delta_q[i])
       vp9_enable_segfeature(xd, i, SEG_LVL_ALT_Q);
     else
diff --git a/vp9/encoder/vp9_quantize.c b/vp9/encoder/vp9_quantize.c
index 18f0f4f..78ea78c 100644
--- a/vp9/encoder/vp9_quantize.c
+++ b/vp9/encoder/vp9_quantize.c
@@ -28,42 +28,29 @@
 
 void vp9_ht_quantize_b_4x4(MACROBLOCK *mb, int b_idx, TX_TYPE tx_type) {
   MACROBLOCKD *const xd = &mb->e_mbd;
-  BLOCK *const b = &mb->block[0];
   BLOCKD *const d = &xd->block[0];
   int i, rc, eob;
   int zbin;
   int x, y, z, sz;
-  int16_t *coeff_ptr       = mb->coeff + b_idx * 16;
+  int16_t *coeff_ptr       = BLOCK_OFFSET(mb->plane[0].coeff, b_idx, 16);
   // ht is luma-only
   int16_t *qcoeff_ptr      = BLOCK_OFFSET(xd->plane[0].qcoeff, b_idx, 16);
   int16_t *dqcoeff_ptr     = BLOCK_OFFSET(xd->plane[0].dqcoeff, b_idx, 16);
-  int16_t *zbin_boost_ptr  = b->zrun_zbin_boost;
-  int16_t *zbin_ptr        = b->zbin;
-  int16_t *round_ptr       = b->round;
-  int16_t *quant_ptr       = b->quant;
-  uint8_t *quant_shift_ptr = b->quant_shift;
+  int16_t *zbin_boost_ptr  = mb->plane[0].zrun_zbin_boost;
+  int16_t *zbin_ptr        = mb->plane[0].zbin;
+  int16_t *round_ptr       = mb->plane[0].round;
+  int16_t *quant_ptr       = mb->plane[0].quant;
+  uint8_t *quant_shift_ptr = mb->plane[0].quant_shift;
   int16_t *dequant_ptr     = d->dequant;
-  int zbin_oq_value        = b->zbin_extra;
-  const int *pt_scan;
-
-  switch (tx_type) {
-    case ADST_DCT:
-      pt_scan = vp9_row_scan_4x4;
-      break;
-    case DCT_ADST:
-      pt_scan = vp9_col_scan_4x4;
-      break;
-    default:
-      pt_scan = vp9_default_zig_zag1d_4x4;
-      break;
-  }
+  int zbin_oq_value        = mb->plane[0].zbin_extra;
+  const int *pt_scan = get_scan_4x4(tx_type);
 
   vpx_memset(qcoeff_ptr, 0, 32);
   vpx_memset(dqcoeff_ptr, 0, 32);
 
   eob = -1;
 
-  if (!b->skip_block) {
+  if (!mb->skip_block) {
     for (i = 0; i < 16; i++) {
       rc   = pt_scan[i];
       z    = coeff_ptr[rc];
@@ -84,7 +71,7 @@
 
         if (y) {
           eob = i;                                // last nonzero coeffs
-          zbin_boost_ptr = b->zrun_zbin_boost;    // reset zero runlength
+          zbin_boost_ptr = mb->plane[0].zrun_zbin_boost;  // reset zero run len
         }
       }
     }
@@ -97,23 +84,23 @@
   MACROBLOCKD *const xd = &mb->e_mbd;
   const struct plane_block_idx pb_idx = plane_block_idx(y_blocks, b_idx);
   const int c_idx = plane_idx(pb_idx.plane);
-  BLOCK *const b = &mb->block[c_idx];
   BLOCKD *const d = &xd->block[c_idx];
   int i, rc, eob;
   int zbin;
   int x, y, z, sz;
-  int16_t *coeff_ptr       = mb->coeff + b_idx * 16;
+  int16_t *coeff_ptr       = BLOCK_OFFSET(mb->plane[pb_idx.plane].coeff,
+                                          pb_idx.block, 16);
   int16_t *qcoeff_ptr      = BLOCK_OFFSET(xd->plane[pb_idx.plane].qcoeff,
                                           pb_idx.block, 16);
   int16_t *dqcoeff_ptr     = BLOCK_OFFSET(xd->plane[pb_idx.plane].dqcoeff,
                                           pb_idx.block, 16);
-  int16_t *zbin_boost_ptr  = b->zrun_zbin_boost;
-  int16_t *zbin_ptr        = b->zbin;
-  int16_t *round_ptr       = b->round;
-  int16_t *quant_ptr       = b->quant;
-  uint8_t *quant_shift_ptr = b->quant_shift;
+  int16_t *zbin_boost_ptr  = mb->plane[pb_idx.plane].zrun_zbin_boost;
+  int16_t *zbin_ptr        = mb->plane[pb_idx.plane].zbin;
+  int16_t *round_ptr       = mb->plane[pb_idx.plane].round;
+  int16_t *quant_ptr       = mb->plane[pb_idx.plane].quant;
+  uint8_t *quant_shift_ptr = mb->plane[pb_idx.plane].quant_shift;
   int16_t *dequant_ptr     = d->dequant;
-  int zbin_oq_value        = b->zbin_extra;
+  int zbin_oq_value        = mb->plane[pb_idx.plane].zbin_extra;
 
   if (c_idx == 0) assert(pb_idx.plane == 0);
   if (c_idx == 16) assert(pb_idx.plane == 1);
@@ -123,7 +110,7 @@
 
   eob = -1;
 
-  if (!b->skip_block) {
+  if (!mb->skip_block) {
     for (i = 0; i < 16; i++) {
       rc   = vp9_default_zig_zag1d_4x4[i];
       z    = coeff_ptr[rc];
@@ -145,7 +132,7 @@
 
         if (y) {
           eob = i;                                // last nonzero coeffs
-          zbin_boost_ptr = b->zrun_zbin_boost;    // reset zero runlength
+          zbin_boost_ptr = mb->plane[pb_idx.plane].zrun_zbin_boost;
         }
       }
     }
@@ -163,21 +150,10 @@
                                      pb_idx.block, 16);
   int16_t *dqcoeff_ptr = BLOCK_OFFSET(xd->plane[pb_idx.plane].dqcoeff,
                                       pb_idx.block, 16);
-  BLOCK *const b = &mb->block[c_idx];
+  int16_t *coeff_ptr = BLOCK_OFFSET(mb->plane[pb_idx.plane].coeff,
+                                    pb_idx.block, 16);
   BLOCKD *const d = &xd->block[c_idx];
-  const int *pt_scan;
-
-  switch (tx_type) {
-    case ADST_DCT:
-      pt_scan = vp9_row_scan_8x8;
-      break;
-    case DCT_ADST:
-      pt_scan = vp9_col_scan_8x8;
-      break;
-    default:
-      pt_scan = vp9_default_zig_zag1d_8x8;
-      break;
-  }
+  const int *pt_scan = get_scan_8x8(tx_type);
 
   if (c_idx == 0) assert(pb_idx.plane == 0);
   if (c_idx == 16) assert(pb_idx.plane == 1);
@@ -185,19 +161,18 @@
   vpx_memset(qcoeff_ptr, 0, 64 * sizeof(int16_t));
   vpx_memset(dqcoeff_ptr, 0, 64 * sizeof(int16_t));
 
-  if (!b->skip_block) {
+  if (!mb->skip_block) {
     int i, rc, eob;
     int zbin;
     int x, y, z, sz;
     int zero_run;
-    int16_t *zbin_boost_ptr = b->zrun_zbin_boost;
-    int16_t *coeff_ptr  = mb->coeff + 16 * b_idx;
-    int16_t *zbin_ptr   = b->zbin;
-    int16_t *round_ptr  = b->round;
-    int16_t *quant_ptr  = b->quant;
-    uint8_t *quant_shift_ptr = b->quant_shift;
+    int16_t *zbin_boost_ptr = mb->plane[pb_idx.plane].zrun_zbin_boost;
+    int16_t *zbin_ptr   = mb->plane[pb_idx.plane].zbin;
+    int16_t *round_ptr  = mb->plane[pb_idx.plane].round;
+    int16_t *quant_ptr  = mb->plane[pb_idx.plane].quant;
+    uint8_t *quant_shift_ptr = mb->plane[pb_idx.plane].quant_shift;
     int16_t *dequant_ptr = d->dequant;
-    int zbin_oq_value = b->zbin_extra;
+    int zbin_oq_value = mb->plane[pb_idx.plane].zbin_extra;
 
     eob = -1;
 
@@ -311,33 +286,23 @@
   MACROBLOCKD *const xd = &mb->e_mbd;
   const struct plane_block_idx pb_idx = plane_block_idx(y_blocks, b_idx);
   const int c_idx = plane_idx(pb_idx.plane);
-  BLOCK *const b = &mb->block[c_idx];
   BLOCKD *const d = &xd->block[c_idx];
-  const int *pt_scan;
-
-  switch (tx_type) {
-    case ADST_DCT:
-      pt_scan = vp9_row_scan_16x16;
-      break;
-    case DCT_ADST:
-      pt_scan = vp9_col_scan_16x16;
-      break;
-    default:
-      pt_scan = vp9_default_zig_zag1d_16x16;
-      break;
-  }
+  const int *pt_scan = get_scan_16x16(tx_type);
 
   if (c_idx == 0) assert(pb_idx.plane == 0);
   if (c_idx == 16) assert(pb_idx.plane == 1);
   if (c_idx == 20) assert(pb_idx.plane == 2);
-  quantize(b->zrun_zbin_boost,
-           mb->coeff + 16 * b_idx,
-           256, b->skip_block,
-           b->zbin, b->round, b->quant, b->quant_shift,
+  quantize(mb->plane[pb_idx.plane].zrun_zbin_boost,
+           BLOCK_OFFSET(mb->plane[pb_idx.plane].coeff, pb_idx.block, 16),
+           256, mb->skip_block,
+           mb->plane[pb_idx.plane].zbin,
+           mb->plane[pb_idx.plane].round,
+           mb->plane[pb_idx.plane].quant,
+           mb->plane[pb_idx.plane].quant_shift,
            BLOCK_OFFSET(xd->plane[pb_idx.plane].qcoeff, pb_idx.block, 16),
            BLOCK_OFFSET(xd->plane[pb_idx.plane].dqcoeff, pb_idx.block, 16),
            d->dequant,
-           b->zbin_extra,
+           mb->plane[pb_idx.plane].zbin_extra,
            &xd->plane[pb_idx.plane].eobs[pb_idx.block],
            pt_scan, 1);
 }
@@ -346,21 +311,22 @@
   MACROBLOCKD *const xd = &mb->e_mbd;
   const struct plane_block_idx pb_idx = plane_block_idx(y_blocks, b_idx);
   const int c_idx = plane_idx(pb_idx.plane);
-  BLOCK *const b = &mb->block[c_idx];
   BLOCKD *const d = &xd->block[c_idx];
 
   if (c_idx == 0) assert(pb_idx.plane == 0);
   if (c_idx == 16) assert(pb_idx.plane == 1);
   if (c_idx == 20) assert(pb_idx.plane == 2);
-  quantize(b->zrun_zbin_boost,
-           mb->coeff + b_idx * 16,
-           1024, b->skip_block,
-           b->zbin,
-           b->round, b->quant, b->quant_shift,
+  quantize(mb->plane[pb_idx.plane].zrun_zbin_boost,
+           BLOCK_OFFSET(mb->plane[pb_idx.plane].coeff, pb_idx.block, 16),
+           1024, mb->skip_block,
+           mb->plane[pb_idx.plane].zbin,
+           mb->plane[pb_idx.plane].round,
+           mb->plane[pb_idx.plane].quant,
+           mb->plane[pb_idx.plane].quant_shift,
            BLOCK_OFFSET(xd->plane[pb_idx.plane].qcoeff, pb_idx.block, 16),
            BLOCK_OFFSET(xd->plane[pb_idx.plane].dqcoeff, pb_idx.block, 16),
            d->dequant,
-           b->zbin_extra,
+           mb->plane[pb_idx.plane].zbin_extra,
            &xd->plane[pb_idx.plane].eobs[pb_idx.block],
            vp9_default_zig_zag1d_32x32, 2);
 }
@@ -556,55 +522,46 @@
   zbin_extra = (cpi->common.y_dequant[qindex][1] *
                  (cpi->zbin_mode_boost + x->act_zbin_adj)) >> 7;
 
-  for (i = 0; i < 16; i++) {
-    x->block[i].quant = cpi->Y1quant[qindex];
-    x->block[i].quant_shift = cpi->Y1quant_shift[qindex];
-    x->block[i].zbin = cpi->Y1zbin[qindex];
-    x->block[i].round = cpi->Y1round[qindex];
+  x->plane[0].quant = cpi->Y1quant[qindex];
+  x->plane[0].quant_shift = cpi->Y1quant_shift[qindex];
+  x->plane[0].zbin = cpi->Y1zbin[qindex];
+  x->plane[0].round = cpi->Y1round[qindex];
+  x->plane[0].zrun_zbin_boost = cpi->zrun_zbin_boost_y1[qindex];
+  x->plane[0].zbin_extra = (int16_t)zbin_extra;
+  for (i = 0; i < 16; i++)
     x->e_mbd.block[i].dequant = cpi->common.y_dequant[qindex];
-    x->block[i].zrun_zbin_boost = cpi->zrun_zbin_boost_y1[qindex];
-    x->block[i].zbin_extra = (int16_t)zbin_extra;
-
-    // Segment skip feature.
-    x->block[i].skip_block =
-      vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP);
-  }
 
   // UV
   zbin_extra = (cpi->common.uv_dequant[qindex][1] *
                 (cpi->zbin_mode_boost + x->act_zbin_adj)) >> 7;
 
-  for (i = 16; i < 24; i++) {
-    x->block[i].quant = cpi->UVquant[qindex];
-    x->block[i].quant_shift = cpi->UVquant_shift[qindex];
-    x->block[i].zbin = cpi->UVzbin[qindex];
-    x->block[i].round = cpi->UVround[qindex];
-    x->e_mbd.block[i].dequant = cpi->common.uv_dequant[qindex];
-    x->block[i].zrun_zbin_boost = cpi->zrun_zbin_boost_uv[qindex];
-    x->block[i].zbin_extra = (int16_t)zbin_extra;
-
-    // Segment skip feature.
-    x->block[i].skip_block =
-        vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP);
+  for (i = 1; i < 3; i++) {
+    x->plane[i].quant = cpi->UVquant[qindex];
+    x->plane[i].quant_shift = cpi->UVquant_shift[qindex];
+    x->plane[i].zbin = cpi->UVzbin[qindex];
+    x->plane[i].round = cpi->UVround[qindex];
+    x->plane[i].zrun_zbin_boost = cpi->zrun_zbin_boost_uv[qindex];
+    x->plane[i].zbin_extra = (int16_t)zbin_extra;
   }
+  for (i = 16; i < 24; i++)
+    x->e_mbd.block[i].dequant = cpi->common.uv_dequant[qindex];
+
+  x->skip_block = vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP);
 
   /* save this macroblock QIndex for vp9_update_zbin_extra() */
   x->e_mbd.q_index = qindex;
 }
 
 void vp9_update_zbin_extra(VP9_COMP *cpi, MACROBLOCK *x) {
-  int i;
   const int qindex = x->e_mbd.q_index;
   const int y_zbin_extra = (cpi->common.y_dequant[qindex][1] *
                 (cpi->zbin_mode_boost + x->act_zbin_adj)) >> 7;
   const int uv_zbin_extra = (cpi->common.uv_dequant[qindex][1] *
                   (cpi->zbin_mode_boost + x->act_zbin_adj)) >> 7;
 
-  for (i = 0; i < 16; i++)
-    x->block[i].zbin_extra = (int16_t)y_zbin_extra;
-
-  for (i = 16; i < 24; i++)
-    x->block[i].zbin_extra = (int16_t)uv_zbin_extra;
+  x->plane[0].zbin_extra = (int16_t)y_zbin_extra;
+  x->plane[1].zbin_extra = (int16_t)uv_zbin_extra;
+  x->plane[2].zbin_extra = (int16_t)uv_zbin_extra;
 }
 
 void vp9_frame_init_quantizer(VP9_COMP *cpi) {
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index 03e47f0..6267697 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -352,13 +352,7 @@
       l_ec = *l;
       coef_probs = cm->fc.coef_probs_4x4;
       seg_eob = 16;
-      if (tx_type == ADST_DCT) {
-        scan = vp9_row_scan_4x4;
-      } else if (tx_type == DCT_ADST) {
-        scan = vp9_col_scan_4x4;
-      } else {
-        scan = vp9_default_zig_zag1d_4x4;
-      }
+      scan = get_scan_4x4(tx_type);
 #if CONFIG_CODE_ZEROGROUP
       zpc_probs = &cm->fc.zpc_probs_4x4;
 #endif
@@ -372,13 +366,7 @@
           get_tx_type_8x8(xd, y + (x >> 1)) : DCT_DCT;
       a_ec = (a[0] + a[1]) != 0;
       l_ec = (l[0] + l[1]) != 0;
-      if (tx_type == ADST_DCT) {
-        scan = vp9_row_scan_8x8;
-      } else if (tx_type == DCT_ADST) {
-        scan = vp9_col_scan_8x8;
-      } else {
-        scan = vp9_default_zig_zag1d_8x8;
-      }
+      scan = get_scan_8x8(tx_type);
       coef_probs = cm->fc.coef_probs_8x8;
       seg_eob = 64;
 #if CONFIG_CODE_ZEROGROUP
@@ -392,13 +380,7 @@
       const int x = ib & ((1 << sz) - 1), y = ib - x;
       TX_TYPE tx_type = (type == PLANE_TYPE_Y_WITH_DC) ?
           get_tx_type_16x16(xd, y + (x >> 2)) : DCT_DCT;
-      if (tx_type == ADST_DCT) {
-        scan = vp9_row_scan_16x16;
-      } else if (tx_type == DCT_ADST) {
-        scan = vp9_col_scan_16x16;
-      } else {
-        scan = vp9_default_zig_zag1d_16x16;
-      }
+      scan = get_scan_16x16(tx_type);
       coef_probs = cm->fc.coef_probs_16x16;
       seg_eob = 256;
       if (type == PLANE_TYPE_UV) {
@@ -648,13 +630,13 @@
                                  rd[TX_4X4][1] : rd[TX_8X8][1];
 }
 
-static int vp9_sb_block_error_c(int16_t *coeff, int16_t *dqcoeff,
-                                int block_size, int shift) {
+static int block_error(int16_t *coeff, int16_t *dqcoeff,
+                       int block_size, int shift) {
   int i;
   int64_t error = 0;
 
   for (i = 0; i < block_size; i++) {
-    unsigned int this_diff = coeff[i] - dqcoeff[i];
+    int this_diff = coeff[i] - dqcoeff[i];
     error += this_diff * this_diff;
   }
   error >>= shift;
@@ -662,24 +644,24 @@
   return error > INT_MAX ? INT_MAX : (int)error;
 }
 
-static int vp9_sb_uv_block_error_c(int16_t *coeff,
-                                   int16_t *dqcoeff0, int16_t *dqcoeff1,
-                                   int block_size, int shift) {
-  int i;
-  int64_t error = 0;
+static int block_error_sby(MACROBLOCK *x, int block_size, int shift) {
+  return block_error(x->plane[0].coeff, x->e_mbd.plane[0].dqcoeff,
+                     block_size, shift);
+}
 
-  for (i = 0; i < block_size / 2; i++) {
-    unsigned int this_diff = coeff[i] - dqcoeff0[i];
-    error += this_diff * this_diff;
-  }
-  coeff += block_size / 2;
-  for (i = 0; i < block_size / 2; i++) {
-    unsigned int this_diff = coeff[i] - dqcoeff1[i];
-    error += this_diff * this_diff;
-  }
-  error >>= shift;
+static int block_error_sbuv(MACROBLOCK *x, BLOCK_SIZE_TYPE bsize, int shift) {
+  const int bwl = b_width_log2(bsize), bhl = b_height_log2(bsize);
+  int64_t sum = 0;
+  int plane;
 
-  return error > INT_MAX ? INT_MAX : (int)error;
+  for (plane = 1; plane < MAX_MB_PLANE; plane++) {
+    const int subsampling = x->e_mbd.plane[plane].subsampling_x +
+                            x->e_mbd.plane[plane].subsampling_y;
+    sum += block_error(x->plane[plane].coeff, x->e_mbd.plane[plane].dqcoeff,
+                       16 << (bwl + bhl - subsampling), 0);
+  }
+  sum >>= shift;
+  return sum > INT_MAX ? INT_MAX : (int)sum;
 }
 
 static int rdcost_sby_4x4(VP9_COMMON *const cm, MACROBLOCK *x,
@@ -716,8 +698,7 @@
   vp9_transform_sby_4x4(x, bsize);
   vp9_quantize_sby_4x4(x, bsize);
 
-  *distortion = vp9_sb_block_error_c(x->coeff, xd->plane[0].dqcoeff,
-                                     16 << (bwl + bhl), 2);
+  *distortion = block_error_sby(x, 16 << (bwl + bhl), 2);
   *rate       = rdcost_sby_4x4(cm, x, bsize);
   *skippable  = vp9_sby_is_skippable(xd, bsize);
 }
@@ -749,15 +730,14 @@
 static void super_block_yrd_8x8(VP9_COMMON *const cm, MACROBLOCK *x,
                                 int *rate, int *distortion, int *skippable,
                                 BLOCK_SIZE_TYPE bsize) {
-  const int bwl = mb_width_log2(bsize) + 1, bhl = mb_height_log2(bsize) + 1;
+  const int bwl = b_width_log2(bsize), bhl = b_height_log2(bsize);
   MACROBLOCKD *const xd = &x->e_mbd;
 
   xd->mode_info_context->mbmi.txfm_size = TX_8X8;
   vp9_transform_sby_8x8(x, bsize);
   vp9_quantize_sby_8x8(x, bsize);
 
-  *distortion = vp9_sb_block_error_c(x->coeff, xd->plane[0].dqcoeff,
-                                     64 << (bhl + bwl), 2);
+  *distortion = block_error_sby(x, 16 << (bhl + bwl), 2);
   *rate       = rdcost_sby_8x8(cm, x, bsize);
   *skippable  = vp9_sby_is_skippable(xd, bsize);
 }
@@ -787,15 +767,14 @@
 static void super_block_yrd_16x16(VP9_COMMON *const cm, MACROBLOCK *x,
                                   int *rate, int *distortion, int *skippable,
                                   BLOCK_SIZE_TYPE bsize) {
-  const int bwl = mb_width_log2(bsize), bhl = mb_height_log2(bsize);
+  const int bwl = b_width_log2(bsize), bhl = b_height_log2(bsize);
   MACROBLOCKD *const xd = &x->e_mbd;
 
   xd->mode_info_context->mbmi.txfm_size = TX_16X16;
   vp9_transform_sby_16x16(x, bsize);
   vp9_quantize_sby_16x16(x, bsize);
 
-  *distortion = vp9_sb_block_error_c(x->coeff, xd->plane[0].dqcoeff,
-                                     256 << (bwl + bhl), 2);
+  *distortion = block_error_sby(x, 16 << (bwl + bhl), 2);
   *rate       = rdcost_sby_16x16(cm, x, bsize);
   *skippable  = vp9_sby_is_skippable(xd, bsize);
 }
@@ -827,15 +806,14 @@
 static void super_block_yrd_32x32(VP9_COMMON *const cm, MACROBLOCK *x,
                                   int *rate, int *distortion, int *skippable,
                                   BLOCK_SIZE_TYPE bsize) {
-  const int bwl = mb_width_log2(bsize) - 1, bhl = mb_height_log2(bsize) - 1;
+  const int bwl = b_width_log2(bsize), bhl = b_height_log2(bsize);
   MACROBLOCKD *const xd = &x->e_mbd;
 
   xd->mode_info_context->mbmi.txfm_size = TX_32X32;
   vp9_transform_sby_32x32(x, bsize);
   vp9_quantize_sby_32x32(x, bsize);
 
-  *distortion = vp9_sb_block_error_c(x->coeff, xd->plane[0].dqcoeff,
-                                     1024 << (bwl + bhl), 0);
+  *distortion = block_error_sby(x, 16 << (bwl + bhl), 0);
   *rate       = rdcost_sby_32x32(cm, x, bsize);
   *skippable  = vp9_sby_is_skippable(xd, bsize);
 }
@@ -845,12 +823,9 @@
                             int *skip, BLOCK_SIZE_TYPE bs,
                             int64_t txfm_cache[NB_TXFM_MODES]) {
   VP9_COMMON *const cm = &cpi->common;
-  MACROBLOCKD *const xd = &x->e_mbd;
   int r[TX_SIZE_MAX_SB][2], d[TX_SIZE_MAX_SB], s[TX_SIZE_MAX_SB];
-  uint8_t *src = x->src.y_buffer, *dst = xd->plane[0].dst.buf;
-  int src_y_stride = x->src.y_stride, dst_y_stride = xd->plane[0].dst.stride;
 
-  vp9_subtract_sby_s_c(x->src_diff, src, src_y_stride, dst, dst_y_stride, bs);
+  vp9_subtract_sby(x, bs);
 
   if (bs >= BLOCK_SIZE_SB32X32)
     super_block_yrd_32x32(cm, x, &r[TX_32X32][0], &d[TX_32X32], &s[TX_32X32],
@@ -877,7 +852,10 @@
   VP9_COMMON *const cm = &cpi->common;
   BLOCK *be = x->block + ib;
   BLOCKD *b = xd->block + ib;
-
+  int16_t* const src_diff =
+      raster_block_offset_int16(xd, BLOCK_SIZE_MB16X16, 0, ib,
+                                x->plane[0].src_diff);
+  int16_t* const coeff = BLOCK_OFFSET(x->plane[0].coeff, ib, 16);
   ENTROPY_CONTEXT ta = *a, tempa = *a;
   ENTROPY_CONTEXT tl = *l, templ = *l;
   TX_TYPE tx_type = DCT_DCT;
@@ -917,15 +895,17 @@
 #endif
 
     vp9_intra4x4_predict(xd, b, mode, *(b->base_dst) + b->dst, b->dst_stride);
-    vp9_subtract_b(be, b, 16);
+    vp9_subtract_block(4, 4, src_diff, 16,
+                       *(be->base_src) + be->src, be->src_stride,
+                       *(b->base_dst) + b->dst, b->dst_stride);
 
     b->bmi.as_mode.first = mode;
     tx_type = get_tx_type_4x4(xd, be - x->block);
     if (tx_type != DCT_DCT) {
-      vp9_short_fht4x4(be->src_diff, be->coeff, 16, tx_type);
+      vp9_short_fht4x4(src_diff, coeff, 16, tx_type);
       vp9_ht_quantize_b_4x4(x, be - x->block, tx_type);
     } else {
-      x->fwd_txm4x4(be->src_diff, be->coeff, 32);
+      x->fwd_txm4x4(src_diff, coeff, 32);
       x->quantize_b_4x4(x, be - x->block, 16);
     }
 
@@ -935,7 +915,7 @@
     ratey = cost_coeffs(cm, x, b - xd->block,
                         PLANE_TYPE_Y_WITH_DC, &tempa, &templ, TX_4X4, 16);
     rate += ratey;
-    distortion = vp9_block_error(be->coeff,
+    distortion = vp9_block_error(coeff,
                                  BLOCK_OFFSET(xd->plane[0].dqcoeff, ib, 16),
                                  16) >> 2;
 
@@ -1107,10 +1087,13 @@
   ENTROPY_CONTEXT_PLANES ta, tl;
   ENTROPY_CONTEXT *ta0, *ta1, besta0 = 0, besta1 = 0;
   ENTROPY_CONTEXT *tl0, *tl1, bestl0 = 0, bestl1 = 0;
-
   // perform transformation of dimension 8x8
   // note the input and output index mapping
   int idx = (ib & 0x02) ? (ib + 2) : ib;
+  int16_t* const src_diff =
+      raster_block_offset_int16(xd, BLOCK_SIZE_MB16X16, 0, ib,
+                                x->plane[0].src_diff);
+  int16_t* const coeff = BLOCK_OFFSET(x->plane[0].coeff, idx, 16);
 
   assert(ib < 16);
   for (mode = DC_PRED; mode <= TM_PRED; mode++) {
@@ -1123,18 +1106,20 @@
 
     vp9_intra8x8_predict(xd, b, mode, *(b->base_dst) + b->dst, b->dst_stride);
 
-    vp9_subtract_4b_c(be, b, 16);
+    vp9_subtract_block(8, 8, src_diff, 16,
+                       *(be->base_src) + be->src, be->src_stride,
+                       *(b->base_dst) + b->dst, b->dst_stride);
 
     if (xd->mode_info_context->mbmi.txfm_size == TX_8X8) {
       TX_TYPE tx_type = get_tx_type_8x8(xd, ib);
       if (tx_type != DCT_DCT)
-        vp9_short_fht8x8(be->src_diff, (x->block + idx)->coeff, 16, tx_type);
+        vp9_short_fht8x8(src_diff, coeff, 16, tx_type);
       else
-        x->fwd_txm8x8(be->src_diff, (x->block + idx)->coeff, 32);
+        x->fwd_txm8x8(src_diff, coeff, 32);
       x->quantize_b_8x8(x, idx, tx_type, 16);
 
       // compute quantization mse of 8x8 block
-      distortion = vp9_block_error_c((x->block + idx)->coeff,
+      distortion = vp9_block_error_c(coeff,
           BLOCK_OFFSET(xd->plane[0].dqcoeff, idx, 16), 64);
 
       vpx_memcpy(&ta, a, sizeof(ENTROPY_CONTEXT_PLANES));
@@ -1162,23 +1147,29 @@
       distortion = 0;
       rate_t = 0;
       for (i = 0; i < 4; ++i) {
+        int16_t* const src_diff =
+            raster_block_offset_int16(xd, BLOCK_SIZE_MB16X16,
+                                      0, ib + iblock[i],
+                                      x->plane[0].src_diff);
+        int16_t* const coeff = BLOCK_OFFSET(x->plane[0].coeff,
+                                            ib + iblock[i], 16);
         int do_two = 0;
         b = &xd->block[ib + iblock[i]];
         be = &x->block[ib + iblock[i]];
         tx_type = get_tx_type_4x4(xd, ib + iblock[i]);
         if (tx_type != DCT_DCT) {
-          vp9_short_fht4x4(be->src_diff, be->coeff, 16, tx_type);
+          vp9_short_fht4x4(src_diff, coeff, 16, tx_type);
           vp9_ht_quantize_b_4x4(x, ib + iblock[i], tx_type);
         } else if (!(i & 1) &&
                    get_tx_type_4x4(xd, ib + iblock[i] + 1) == DCT_DCT) {
-          x->fwd_txm8x4(be->src_diff, be->coeff, 32);
+          x->fwd_txm8x4(src_diff, coeff, 32);
           x->quantize_b_4x4_pair(x, ib + iblock[i], ib + iblock[i] + 1, 16);
           do_two = 1;
         } else {
-          x->fwd_txm4x4(be->src_diff, be->coeff, 32);
+          x->fwd_txm4x4(src_diff, coeff, 32);
           x->quantize_b_4x4(x, ib + iblock[i], 16);
         }
-        distortion += vp9_block_error_c(be->coeff,
+        distortion += vp9_block_error_c(coeff,
             BLOCK_OFFSET(xd->plane[0].dqcoeff, ib + iblock[i], 16),
             16 << do_two);
         rate_t += cost_coeffs(cm, x, ib + iblock[i], PLANE_TYPE_Y_WITH_DC,
@@ -1376,17 +1367,13 @@
 static void super_block_uvrd_4x4(VP9_COMMON *const cm, MACROBLOCK *x,
                                  int *rate, int *distortion, int *skip,
                                  BLOCK_SIZE_TYPE bsize) {
-  const int bwl = mb_width_log2(bsize) + 2, bhl = mb_height_log2(bsize) + 2;
   MACROBLOCKD *const xd = &x->e_mbd;
 
   vp9_transform_sbuv_4x4(x, bsize);
   vp9_quantize_sbuv_4x4(x, bsize);
 
   *rate       = rd_cost_sbuv_4x4(cm, x, bsize);
-  *distortion = vp9_sb_uv_block_error_c(x->coeff + (16 << (bwl + bhl)),
-                                        xd->plane[1].dqcoeff,
-                                        xd->plane[2].dqcoeff,
-                                        32 << (bwl + bhl - 2), 2);
+  *distortion = block_error_sbuv(x, bsize, 2);
   *skip       = vp9_sbuv_is_skippable(xd, bsize);
 }
 
@@ -1421,17 +1408,13 @@
 static void super_block_uvrd_8x8(VP9_COMMON *const cm, MACROBLOCK *x,
                                  int *rate, int *distortion, int *skip,
                                  BLOCK_SIZE_TYPE bsize) {
-  const int bwl = mb_width_log2(bsize) + 1, bhl = mb_height_log2(bsize) + 1;
   MACROBLOCKD *const xd = &x->e_mbd;
 
   vp9_transform_sbuv_8x8(x, bsize);
   vp9_quantize_sbuv_8x8(x, bsize);
 
   *rate       = rd_cost_sbuv_8x8(cm, x, bsize);
-  *distortion = vp9_sb_uv_block_error_c(x->coeff + (64 << (bwl + bhl)),
-                                        xd->plane[1].dqcoeff,
-                                        xd->plane[2].dqcoeff,
-                                        128 << (bwl + bhl - 2), 2);
+  *distortion = block_error_sbuv(x, bsize, 2);
   *skip       = vp9_sbuv_is_skippable(xd, bsize);
 }
 
@@ -1466,17 +1449,13 @@
 static void super_block_uvrd_16x16(VP9_COMMON *const cm, MACROBLOCK *x,
                                    int *rate, int *distortion, int *skip,
                                    BLOCK_SIZE_TYPE bsize) {
-  const int bwl = mb_width_log2(bsize), bhl = mb_height_log2(bsize);
   MACROBLOCKD *const xd = &x->e_mbd;
 
   vp9_transform_sbuv_16x16(x, bsize);
   vp9_quantize_sbuv_16x16(x, bsize);
 
   *rate       = rd_cost_sbuv_16x16(cm, x, bsize);
-  *distortion = vp9_sb_uv_block_error_c(x->coeff + (256 << (bwl + bhl)),
-                                        xd->plane[1].dqcoeff,
-                                        xd->plane[2].dqcoeff,
-                                        512 << (bwl + bhl - 2), 2);
+  *distortion = block_error_sbuv(x, bsize, 2);
   *skip       = vp9_sbuv_is_skippable(xd, bsize);
 }
 
@@ -1512,17 +1491,13 @@
 static void super_block_uvrd_32x32(VP9_COMMON *const cm, MACROBLOCK *x,
                                    int *rate, int *distortion, int *skip,
                                    BLOCK_SIZE_TYPE bsize) {
-  const int bwl = mb_width_log2(bsize) - 1, bhl = mb_height_log2(bsize) - 1;
   MACROBLOCKD *const xd = &x->e_mbd;
 
   vp9_transform_sbuv_32x32(x, bsize);
   vp9_quantize_sbuv_32x32(x, bsize);
 
   *rate       = rd_cost_sbuv_32x32(cm, x, bsize);
-  *distortion = vp9_sb_uv_block_error_c(x->coeff + (1024 << (bwl + bhl)),
-                                        xd->plane[1].dqcoeff,
-                                        xd->plane[2].dqcoeff,
-                                        2048 << (bwl + bhl - 2), 0);
+  *distortion = block_error_sbuv(x, bsize, 0);
   *skip       = vp9_sbuv_is_skippable(xd, bsize);
 }
 
@@ -1531,12 +1506,8 @@
                              BLOCK_SIZE_TYPE bsize) {
   MACROBLOCKD *const xd = &x->e_mbd;
   MB_MODE_INFO *const mbmi = &xd->mode_info_context->mbmi;
-  uint8_t *usrc = x->src.u_buffer, *udst = xd->plane[1].dst.buf;
-  uint8_t *vsrc = x->src.v_buffer, *vdst = xd->plane[2].dst.buf;
-  int src_uv_stride = x->src.uv_stride, dst_uv_stride = xd->plane[1].dst.stride;
 
-  vp9_subtract_sbuv_s_c(x->src_diff, usrc, vsrc, src_uv_stride,
-                        udst, vdst, dst_uv_stride, bsize);
+  vp9_subtract_sbuv(x, bsize);
 
   if (mbmi->txfm_size >= TX_32X32 && bsize >= BLOCK_SIZE_SB64X64) {
     super_block_uvrd_32x32(cm, x, rate, distortion, skippable, bsize);
@@ -1738,6 +1709,10 @@
     if (labels[i] == which_label) {
       BLOCKD *bd = &x->e_mbd.block[i];
       BLOCK *be = &x->block[i];
+      int16_t* const src_diff =
+          raster_block_offset_int16(xd, BLOCK_SIZE_MB16X16, 0, i,
+                                    x->plane[0].src_diff);
+      int16_t* const coeff = BLOCK_OFFSET(x->plane[0].coeff, 16, i);
       int thisdistortion;
 
       vp9_build_inter_predictor(*(bd->base_pre) + bd->pre,
@@ -1759,10 +1734,12 @@
             &xd->subpix);
       }
 
-      vp9_subtract_b(be, bd, 16);
-      x->fwd_txm4x4(be->src_diff, be->coeff, 32);
+      vp9_subtract_block(4, 4, src_diff, 16,
+                         *(be->base_src) + be->src, be->src_stride,
+                         *(bd->base_dst) + bd->dst, bd->dst_stride);
+      x->fwd_txm4x4(src_diff, coeff, 32);
       x->quantize_b_4x4(x, i, 16);
-      thisdistortion = vp9_block_error(be->coeff,
+      thisdistortion = vp9_block_error(coeff,
           BLOCK_OFFSET(xd->plane[0].dqcoeff, i, 16), 16);
       *distortion += thisdistortion;
       *labelyrate += cost_coeffs(cm, x, i, PLANE_TYPE_Y_WITH_DC,
@@ -1807,7 +1784,11 @@
       int which_mv;
       const int idx = (ib & 8) + ((ib & 2) << 1);
       BLOCKD *bd = &xd->block[ib];
-      BLOCK *be = &x->block[ib], *be2 = &x->block[idx];
+      BLOCK *be = &x->block[ib];
+      int16_t* const src_diff =
+          raster_block_offset_int16(xd, BLOCK_SIZE_MB16X16, 0, ib,
+                                    x->plane[0].src_diff);
+      int16_t* const coeff = BLOCK_OFFSET(x->plane[0].coeff, idx, 16);
       int thisdistortion;
 
       assert(idx < 16);
@@ -1824,13 +1805,15 @@
             which_mv, &xd->subpix);
       }
 
-      vp9_subtract_4b_c(be, bd, 16);
+      vp9_subtract_block(8, 8, src_diff, 16,
+                         *(be->base_src) + be->src, be->src_stride,
+                         *(bd->base_dst) + bd->dst, bd->dst_stride);
 
       if (xd->mode_info_context->mbmi.txfm_size == TX_4X4) {
         if (otherrd) {
-          x->fwd_txm8x8(be->src_diff, be2->coeff, 32);
+          x->fwd_txm8x8(src_diff, coeff, 32);
           x->quantize_b_8x8(x, idx, DCT_DCT, 16);
-          thisdistortion = vp9_block_error_c(be2->coeff,
+          thisdistortion = vp9_block_error_c(coeff,
               BLOCK_OFFSET(xd->plane[0].dqcoeff, idx, 16), 64);
           otherdist += thisdistortion;
           xd->mode_info_context->mbmi.txfm_size = TX_8X8;
@@ -1841,11 +1824,17 @@
           xd->mode_info_context->mbmi.txfm_size = TX_4X4;
         }
         for (j = 0; j < 4; j += 2) {
+          int16_t* const src_diff =
+              raster_block_offset_int16(xd, BLOCK_SIZE_MB16X16,
+                                        0, ib + iblock[j],
+                                        x->plane[0].src_diff);
+          int16_t* const coeff = BLOCK_OFFSET(x->plane[0].coeff,
+                                              ib + iblock[j], 16);
           bd = &xd->block[ib + iblock[j]];
           be = &x->block[ib + iblock[j]];
-          x->fwd_txm8x4(be->src_diff, be->coeff, 32);
+          x->fwd_txm8x4(src_diff, coeff, 32);
           x->quantize_b_4x4_pair(x, ib + iblock[j], ib + iblock[j] + 1, 16);
-          thisdistortion = vp9_block_error_c(be->coeff,
+          thisdistortion = vp9_block_error_c(coeff,
               BLOCK_OFFSET(xd->plane[0].dqcoeff, ib + iblock[j], 16), 32);
           *distortion += thisdistortion;
           *labelyrate +=
@@ -1863,10 +1852,15 @@
       } else /* 8x8 */ {
         if (otherrd) {
           for (j = 0; j < 4; j += 2) {
-            BLOCK *be = &x->block[ib + iblock[j]];
-            x->fwd_txm8x4(be->src_diff, be->coeff, 32);
+            int16_t* const src_diff =
+                raster_block_offset_int16(xd, BLOCK_SIZE_MB16X16,
+                                          0, ib + iblock[j],
+                                          x->plane[0].src_diff);
+            int16_t* const coeff = BLOCK_OFFSET(x->plane[0].coeff,
+                                                ib + iblock[j], 16);
+            x->fwd_txm8x4(src_diff, coeff, 32);
             x->quantize_b_4x4_pair(x, ib + iblock[j], ib + iblock[j] + 1, 16);
-            thisdistortion = vp9_block_error_c(be->coeff,
+            thisdistortion = vp9_block_error_c(coeff,
                 BLOCK_OFFSET(xd->plane[0].dqcoeff, ib + iblock[j], 16), 32);
             otherdist += thisdistortion;
             xd->mode_info_context->mbmi.txfm_size = TX_4X4;
@@ -1884,9 +1878,9 @@
             xd->mode_info_context->mbmi.txfm_size = TX_8X8;
           }
         }
-        x->fwd_txm8x8(be->src_diff, be2->coeff, 32);
+        x->fwd_txm8x8(src_diff, coeff, 32);
         x->quantize_b_8x8(x, idx, DCT_DCT, 16);
-        thisdistortion = vp9_block_error_c(be2->coeff,
+        thisdistortion = vp9_block_error_c(coeff,
             BLOCK_OFFSET(xd->plane[0].dqcoeff, idx, 16), 64);
         *distortion += thisdistortion;
         *labelyrate += cost_coeffs(cm, x, idx, PLANE_TYPE_Y_WITH_DC,
@@ -3786,12 +3780,7 @@
         vp9_build_inter_predictors_sbuv(&x->e_mbd, mb_row, mb_col,
                                         BLOCK_SIZE_MB16X16);
 
-        vp9_subtract_sbuv_s_c(x->src_diff,
-                              x->src.u_buffer,
-                              x->src.v_buffer, x->src.uv_stride,
-                              xd->plane[1].dst.buf,
-                              xd->plane[2].dst.buf, xd->plane[1].dst.stride,
-                              BLOCK_SIZE_MB16X16);
+        vp9_subtract_sbuv(x, BLOCK_SIZE_MB16X16);
 
         super_block_uvrd_4x4(cm, x, &rate_uv, &distortion_uv,
                              &uv_skippable, BLOCK_SIZE_MB16X16);
diff --git a/vp9/encoder/vp9_segmentation.c b/vp9/encoder/vp9_segmentation.c
index 6336969..56484e6 100644
--- a/vp9/encoder/vp9_segmentation.c
+++ b/vp9/encoder/vp9_segmentation.c
@@ -63,16 +63,18 @@
 static void calc_segtree_probs(MACROBLOCKD *xd,
                                int *segcounts,
                                vp9_prob *segment_tree_probs) {
-  int count1, count2;
-
-  // Total count for all segments
-  count1 = segcounts[0] + segcounts[1];
-  count2 = segcounts[2] + segcounts[3];
-
   // Work out probabilities of each segment
-  segment_tree_probs[0] = get_binary_prob(count1, count2);
-  segment_tree_probs[1] = get_prob(segcounts[0], count1);
-  segment_tree_probs[2] = get_prob(segcounts[2], count2);
+  segment_tree_probs[0] =
+    get_binary_prob(segcounts[0] + segcounts[1] + segcounts[2] + segcounts[3],
+                    segcounts[4] + segcounts[5] + segcounts[6] + segcounts[7]);
+  segment_tree_probs[1] =
+    get_binary_prob(segcounts[0] + segcounts[1], segcounts[2] + segcounts[3]);
+  segment_tree_probs[2] = get_binary_prob(segcounts[0], segcounts[1]);
+  segment_tree_probs[3] = get_binary_prob(segcounts[2], segcounts[3]);
+  segment_tree_probs[4] =
+    get_binary_prob(segcounts[4] + segcounts[5], segcounts[6] + segcounts[7]);
+  segment_tree_probs[5] = get_binary_prob(segcounts[4], segcounts[5]);
+  segment_tree_probs[6] = get_binary_prob(segcounts[6], segcounts[7]);
 }
 
 // Based on set of segment counts and probabilities calculate a cost estimate
@@ -83,81 +85,38 @@
   int count1, count2;
 
   // Cost the top node of the tree
-  count1 = segcounts[0] + segcounts[1];
-  count2 = segcounts[2] + segcounts[3];
+  count1 = segcounts[0] + segcounts[1] + segcounts[2] + segcounts[3];
+  count2 = segcounts[3] + segcounts[4] + segcounts[5] + segcounts[6];
   cost = count1 * vp9_cost_zero(probs[0]) +
          count2 * vp9_cost_one(probs[0]);
 
-  // Now add the cost of each individual segment branch
-  if (count1 > 0)
-    cost += segcounts[0] * vp9_cost_zero(probs[1]) +
-            segcounts[1] * vp9_cost_one(probs[1]);
+  // Cost subsequent levels
+  if (count1 > 0) {
+    count1 = segcounts[0] + segcounts[1];
+    count2 = segcounts[2] + segcounts[3];
+    cost += count1 * vp9_cost_zero(probs[1]) +
+            count2 * vp9_cost_one(probs[1]);
 
-  if (count2 > 0)
-    cost += segcounts[2] * vp9_cost_zero(probs[2]) +
-            segcounts[3] * vp9_cost_one(probs[2]);
+    if (count1 > 0)
+      cost += segcounts[0] * vp9_cost_zero(probs[2]) +
+              segcounts[1] * vp9_cost_one(probs[2]);
+    if (count2 > 0)
+      cost += segcounts[2] * vp9_cost_zero(probs[3]) +
+              segcounts[3] * vp9_cost_one(probs[3]);
+  }
 
-  return cost;
-}
+  if (count2 > 0) {
+    count1 = segcounts[4] + segcounts[5];
+    count2 = segcounts[6] + segcounts[7];
+    cost += count1 * vp9_cost_zero(probs[4]) +
+            count2 * vp9_cost_one(probs[4]);
 
-// Based on set of segment counts calculate a probability tree
-static void calc_segtree_probs_pred(MACROBLOCKD *xd,
-                                    int (*segcounts)[MAX_MB_SEGMENTS],
-                                    vp9_prob *segment_tree_probs,
-                                    vp9_prob *mod_probs) {
-  int count[4];
-
-  assert(!segcounts[0][0] && !segcounts[1][1] &&
-         !segcounts[2][2] && !segcounts[3][3]);
-
-  // Total count for all segments
-  count[0] = segcounts[3][0] + segcounts[1][0] + segcounts[2][0];
-  count[1] = segcounts[2][1] + segcounts[0][1] + segcounts[3][1];
-  count[2] = segcounts[0][2] + segcounts[3][2] + segcounts[1][2];
-  count[3] = segcounts[1][3] + segcounts[2][3] + segcounts[0][3];
-
-  // Work out probabilities of each segment
-  segment_tree_probs[0] = get_binary_prob(count[0] + count[1],
-                                          count[2] + count[3]);
-  segment_tree_probs[1] = get_binary_prob(count[0], count[1]);
-  segment_tree_probs[2] = get_binary_prob(count[2], count[3]);
-
-  // now work out modified counts that the decoder would have
-  count[0] =        segment_tree_probs[0]  *        segment_tree_probs[1];
-  count[1] =        segment_tree_probs[0]  * (256 - segment_tree_probs[1]);
-  count[2] = (256 - segment_tree_probs[0]) *        segment_tree_probs[2];
-  count[3] = (256 - segment_tree_probs[0]) * (256 - segment_tree_probs[2]);
-
-  // Work out modified probabilties depending on what segment was predicted
-  mod_probs[0] = get_binary_prob(count[1], count[2] + count[3]);
-  mod_probs[1] = get_binary_prob(count[0], count[2] + count[3]);
-  mod_probs[2] = get_binary_prob(count[0] + count[1], count[3]);
-  mod_probs[3] = get_binary_prob(count[0] + count[1], count[2]);
-}
-
-// Based on set of segment counts and probabilities calculate a cost estimate
-static int cost_segmap_pred(MACROBLOCKD *xd,
-                            int (*segcounts)[MAX_MB_SEGMENTS],
-                            vp9_prob *probs, vp9_prob *mod_probs) {
-  int pred_seg, cost = 0;
-
-  for (pred_seg = 0; pred_seg < MAX_MB_SEGMENTS; pred_seg++) {
-    int count1, count2;
-
-    // Cost the top node of the tree
-    count1 = segcounts[pred_seg][0] + segcounts[pred_seg][1];
-    count2 = segcounts[pred_seg][2] + segcounts[pred_seg][3];
-    cost += count1 * vp9_cost_zero(mod_probs[pred_seg]) +
-            count2 * vp9_cost_one(mod_probs[pred_seg]);
-
-    // Now add the cost of each individual segment branch
-    if (pred_seg >= 2 && count1) {
-      cost += segcounts[pred_seg][0] * vp9_cost_zero(probs[1]) +
-              segcounts[pred_seg][1] * vp9_cost_one(probs[1]);
-    } else if (pred_seg < 2 && count2 > 0) {
-      cost += segcounts[pred_seg][2] * vp9_cost_zero(probs[2]) +
-              segcounts[pred_seg][3] * vp9_cost_one(probs[2]);
-    }
+    if (count1 > 0)
+      cost += segcounts[4] * vp9_cost_zero(probs[5]) +
+              segcounts[5] * vp9_cost_one(probs[5]);
+    if (count2 > 0)
+      cost += segcounts[6] * vp9_cost_zero(probs[6]) +
+              segcounts[7] * vp9_cost_one(probs[6]);
   }
 
   return cost;
@@ -167,7 +126,7 @@
                        MODE_INFO *mi,
                        int *no_pred_segcounts,
                        int (*temporal_predictor_count)[2],
-                       int (*t_unpred_seg_counts)[MAX_MB_SEGMENTS],
+                       int *t_unpred_seg_counts,
                        int bw, int bh, int mb_row, int mb_col) {
   VP9_COMMON *const cm = &cpi->common;
   MACROBLOCKD *const xd = &cpi->mb.e_mbd;
@@ -197,7 +156,7 @@
 
     if (!seg_predicted)
       // Update the "unpredicted" segment count
-      t_unpred_seg_counts[pred_seg_id][segment_id]++;
+      t_unpred_seg_counts[segment_id]++;
   }
 }
 
@@ -213,11 +172,10 @@
 
   int temporal_predictor_count[PREDICTION_PROBS][2];
   int no_pred_segcounts[MAX_MB_SEGMENTS];
-  int t_unpred_seg_counts[MAX_MB_SEGMENTS][MAX_MB_SEGMENTS];
+  int t_unpred_seg_counts[MAX_MB_SEGMENTS];
 
-  vp9_prob no_pred_tree[MB_FEATURE_TREE_PROBS];
-  vp9_prob t_pred_tree[MB_FEATURE_TREE_PROBS];
-  vp9_prob t_pred_tree_mod[MAX_MB_SEGMENTS];
+  vp9_prob no_pred_tree[MB_SEG_TREE_PROBS];
+  vp9_prob t_pred_tree[MB_SEG_TREE_PROBS];
   vp9_prob t_nopred_prob[PREDICTION_PROBS];
 
   const int mis = cm->mode_info_stride;
@@ -332,10 +290,8 @@
   if (cm->frame_type != KEY_FRAME) {
     // Work out probability tree for coding those segments not
     // predicted using the temporal method and the cost.
-    calc_segtree_probs_pred(xd, t_unpred_seg_counts, t_pred_tree,
-                            t_pred_tree_mod);
-    t_pred_cost = cost_segmap_pred(xd, t_unpred_seg_counts, t_pred_tree,
-                                   t_pred_tree_mod);
+    calc_segtree_probs(xd, t_unpred_seg_counts, t_pred_tree);
+    t_pred_cost = cost_segmap(xd, t_unpred_seg_counts, t_pred_tree);
 
     // Add in the cost of the signalling for each prediction context
     for (i = 0; i < PREDICTION_PROBS; i++) {
@@ -355,8 +311,6 @@
     cm->temporal_update = 1;
     vpx_memcpy(xd->mb_segment_tree_probs,
                t_pred_tree, sizeof(t_pred_tree));
-    vpx_memcpy(xd->mb_segment_mispred_tree_probs,
-               t_pred_tree_mod, sizeof(t_pred_tree_mod));
     vpx_memcpy(&cm->segment_pred_probs,
                t_nopred_prob, sizeof(t_nopred_prob));
   } else {
diff --git a/vp9/encoder/vp9_tokenize.c b/vp9/encoder/vp9_tokenize.c
index f79d033..6f2cbbf 100644
--- a/vp9/encoder/vp9_tokenize.c
+++ b/vp9/encoder/vp9_tokenize.c
@@ -204,14 +204,7 @@
       a_ec = *a;
       l_ec = *l;
       seg_eob = 16;
-      scan = vp9_default_zig_zag1d_4x4;
-      if (tx_type != DCT_DCT) {
-        if (tx_type == ADST_DCT) {
-          scan = vp9_row_scan_4x4;
-        } else if (tx_type == DCT_ADST) {
-          scan = vp9_col_scan_4x4;
-        }
-      }
+      scan = get_scan_4x4(tx_type);
       counts = cpi->coef_counts_4x4;
       coef_probs = cpi->common.fc.coef_probs_4x4;
 #if CONFIG_CODE_ZEROGROUP
@@ -228,14 +221,7 @@
       a_ec = (a[0] + a[1]) != 0;
       l_ec = (l[0] + l[1]) != 0;
       seg_eob = 64;
-      scan = vp9_default_zig_zag1d_8x8;
-      if (tx_type != DCT_DCT) {
-        if (tx_type == ADST_DCT) {
-          scan = vp9_row_scan_8x8;
-        } else if (tx_type == DCT_ADST) {
-          scan = vp9_col_scan_8x8;
-        }
-      }
+      scan = get_scan_8x8(tx_type);
       counts = cpi->coef_counts_8x8;
       coef_probs = cpi->common.fc.coef_probs_8x8;
 #if CONFIG_CODE_ZEROGROUP
@@ -257,14 +243,7 @@
         l_ec = (l[0] + l[1] + l1[0] + l1[1]) != 0;
       }
       seg_eob = 256;
-      scan = vp9_default_zig_zag1d_16x16;
-      if (tx_type != DCT_DCT) {
-        if (tx_type == ADST_DCT) {
-          scan = vp9_row_scan_16x16;
-        } else if (tx_type == DCT_ADST) {
-          scan = vp9_col_scan_16x16;
-        }
-      }
+      scan = get_scan_16x16(tx_type);
       counts = cpi->coef_counts_16x16;
       coef_probs = cpi->common.fc.coef_probs_16x16;
 #if CONFIG_CODE_ZEROGROUP
diff --git a/vp9/encoder/x86/vp9_x86_csystemdependent.c b/vp9/encoder/x86/vp9_x86_csystemdependent.c
index 04383fc..6016e14 100644
--- a/vp9/encoder/x86/vp9_x86_csystemdependent.c
+++ b/vp9/encoder/x86/vp9_x86_csystemdependent.c
@@ -17,7 +17,7 @@
 
 // TODO(jimbankoski) Consider rewriting the c to take the same values rather
 // than going through these pointer conversions
-#if HAVE_MMX
+#if 0 && HAVE_MMX
 void vp9_short_fdct8x4_mmx(short *input, short *output, int pitch) {
   vp9_short_fdct4x4_mmx(input,   output,    pitch);
   vp9_short_fdct4x4_mmx(input + 4, output + 16, pitch);
@@ -38,7 +38,7 @@
 
 #endif
 
-#if HAVE_SSE2
+#if 0 && HAVE_SSE2
 void vp9_subtract_b_sse2_impl(unsigned char *z,  int src_stride,
                               short *diff, unsigned char *predictor,
                               int pitch);
diff --git a/vpx/vp8cx.h b/vpx/vp8cx.h
index 7f19dd0..f8e2ef9 100644
--- a/vpx/vp8cx.h
+++ b/vpx/vp8cx.h
@@ -215,9 +215,13 @@
   unsigned char *roi_map;      /**< specify an id between 0 and 3 for each 16x16 region within a frame */
   unsigned int   rows;         /**< number of rows */
   unsigned int   cols;         /**< number of cols */
-  int     delta_q[4];          /**< quantizer delta [-63, 63] off baseline for regions with id between 0 and 3*/
-  int     delta_lf[4];         /**< loop filter strength delta [-63, 63] for regions with id between 0 and 3 */
-  unsigned int   static_threshold[4];/**< threshold for region to be treated as static */
+  // TODO(paulwilkins): broken for VP9 which has 8 segments
+  // q and loop filter deltas for each segment
+  // (see MAX_MB_SEGMENTS)
+  int     delta_q[4];
+  int     delta_lf[4];
+  // Static breakout threshold for each segment
+  unsigned int   static_threshold[4];
 } vpx_roi_map_t;
 
 /*!\brief  vpx active region map