Merge "Fix mingw build error" into experimental
diff --git a/configure b/configure
index 05e5384..af4e3fb 100755
--- a/configure
+++ b/configure
@@ -243,6 +243,7 @@
     non420
     alpha
     balanced_coeftree
+    new_loopfilter
 "
 CONFIG_LIST="
     external_build
diff --git a/test/borders_test.cc b/test/borders_test.cc
new file mode 100644
index 0000000..8cac4fd
--- /dev/null
+++ b/test/borders_test.cc
@@ -0,0 +1,86 @@
+/*
+ *  Copyright (c) 2012 The WebM project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+#include <climits>
+#include <vector>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+
+namespace {
+
+class BordersTest : public ::libvpx_test::EncoderTest,
+    public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
+ protected:
+  BordersTest() : EncoderTest(GET_PARAM(0)) {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(GET_PARAM(1));
+  }
+
+  virtual bool Continue() const {
+    return !HasFatalFailure() && !abort_;
+  }
+
+  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+                                  ::libvpx_test::Encoder *encoder) {
+    if ( video->frame() == 1) {
+      encoder->Control(VP8E_SET_CPUUSED, 5);
+      encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+      encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
+      encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
+      encoder->Control(VP8E_SET_ARNR_TYPE, 3);
+    }
+  }
+
+  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+    if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) {
+    }
+  }
+};
+
+TEST_P(BordersTest, TestEncodeHighBitrate) {
+  // Validate that this non multiple of 64 wide clip encodes and decodes
+  // without a mismatch when passing in a very low max q.  This pushes
+  // the encoder to producing lots of big partitions which will likely
+  // extend into the border and test the border condition.
+  cfg_.g_lag_in_frames = 25;
+  cfg_.rc_2pass_vbr_minsection_pct = 5;
+  cfg_.rc_2pass_vbr_minsection_pct = 2000;
+  cfg_.rc_target_bitrate = 2000;
+  cfg_.rc_max_quantizer = 10;
+
+  ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
+                                       40);
+
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+TEST_P(BordersTest, TestLowBitrate) {
+  // Validate that this clip encodes and decodes without a mismatch
+  // when passing in a very high min q.  This pushes the encoder to producing
+  // lots of small partitions which might will test the other condition.
+
+  cfg_.g_lag_in_frames = 25;
+  cfg_.rc_2pass_vbr_minsection_pct = 5;
+  cfg_.rc_2pass_vbr_minsection_pct = 2000;
+  cfg_.rc_target_bitrate = 200;
+  cfg_.rc_min_quantizer = 40;
+
+  ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
+                                       40);
+
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+VP9_INSTANTIATE_TEST_CASE(BordersTest, ::testing::Values(
+    ::libvpx_test::kTwoPassGood));
+}  // namespace
diff --git a/test/test-data.sha1 b/test/test-data.sha1
index c1b6a83..98cdda0 100644
--- a/test/test-data.sha1
+++ b/test/test-data.sha1
@@ -1,4 +1,5 @@
 d5dfb0151c9051f8c85999255645d7a23916d3c0  hantro_collage_w352h288.yuv
+b87815bf86020c592ccc7a846ba2e28ec8043902  hantro_odd.yuv
 5184c46ddca8b1fadd16742e8500115bc8f749da  vp80-00-comprehensive-001.ivf
 65bf1bbbced81b97bd030f376d1b7f61a224793f  vp80-00-comprehensive-002.ivf
 906b4c1e99eb734504c504b3f1ad8052137ce672  vp80-00-comprehensive-003.ivf
@@ -120,4 +121,4 @@
 41d70bb5fa45bc88da1604a0af466930b8dd77b5  vp80-05-sharpness-1438.ivf.md5
 086c56378df81b6cee264d7540a7b8f2b405c7a4  vp80-05-sharpness-1439.ivf.md5
 d32dc2c4165eb266ea4c23c14a45459b363def32  vp80-05-sharpness-1440.ivf.md5
-8c69dc3d8e563f56ffab5ad1e400d9e689dd23df  vp80-05-sharpness-1443.ivf.md5
\ No newline at end of file
+8c69dc3d8e563f56ffab5ad1e400d9e689dd23df  vp80-05-sharpness-1443.ivf.md5
diff --git a/test/test.mk b/test/test.mk
index 0d069d0..1e0b217 100644
--- a/test/test.mk
+++ b/test/test.mk
@@ -22,6 +22,7 @@
 LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS)    += error_resilience_test.cc
 LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS)    += i420_video_source.h
 LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += keyframe_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += borders_test.cc
 LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += resize_test.cc
 
 LIBVPX_TEST_SRCS-$(CONFIG_DECODERS)    += ../md5_utils.h ../md5_utils.c
@@ -92,6 +93,7 @@
 ## TEST DATA
 ##
 LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += hantro_collage_w352h288.yuv
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += hantro_odd.yuv
 
 LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-001.ivf
 LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-002.ivf
diff --git a/test/vp9_boolcoder_test.cc b/test/vp9_boolcoder_test.cc
index 5d87ff6..42b2229 100644
--- a/test/vp9_boolcoder_test.cc
+++ b/test/vp9_boolcoder_test.cc
@@ -68,6 +68,9 @@
 
         vp9_stop_encode(&bw);
 
+        // First bit should be zero
+        GTEST_ASSERT_EQ(bw_buffer[0] & 0x80, 0);
+
         vp9_reader br;
         vp9_reader_init(&br, bw_buffer, buffer_size);
         bit_rnd.Reset(random_seed);
diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c
index 930d93f..aec7bff 100644
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -5179,7 +5179,7 @@
 
         if (cm->show_frame)
         {
-
+            cpi->common.show_frame_mi = cpi->common.mi;
             cpi->count ++;
 
             if (cpi->b_calculate_psnr)
diff --git a/vp9/common/vp9_alloccommon.c b/vp9/common/vp9_alloccommon.c
index ef14e1a..4960963 100644
--- a/vp9/common/vp9_alloccommon.c
+++ b/vp9/common/vp9_alloccommon.c
@@ -10,41 +10,39 @@
 
 
 #include "./vpx_config.h"
-#include "vp9/common/vp9_blockd.h"
 #include "vpx_mem/vpx_mem.h"
-#include "vp9/common/vp9_onyxc_int.h"
-#include "vp9/common/vp9_findnearmv.h"
+#include "vp9/common/vp9_blockd.h"
 #include "vp9/common/vp9_entropymode.h"
 #include "vp9/common/vp9_entropymv.h"
+#include "vp9/common/vp9_findnearmv.h"
+#include "vp9/common/vp9_onyxc_int.h"
 #include "vp9/common/vp9_systemdependent.h"
 
-
-void vp9_update_mode_info_border(VP9_COMMON *cpi, MODE_INFO *mi) {
-  const int stride = cpi->mode_info_stride;
+void vp9_update_mode_info_border(VP9_COMMON *cm, MODE_INFO *mi) {
+  const int stride = cm->mode_info_stride;
   int i;
 
   // Clear down top border row
   vpx_memset(mi, 0, sizeof(MODE_INFO) * stride);
 
   // Clear left border column
-  for (i = 1; i < cpi->mi_rows + 1; i++)
+  for (i = 1; i < cm->mi_rows + 1; i++)
     vpx_memset(&mi[i * stride], 0, sizeof(MODE_INFO));
 }
 
-void vp9_update_mode_info_in_image(VP9_COMMON *cpi, MODE_INFO *mi) {
+void vp9_update_mode_info_in_image(VP9_COMMON *cm, MODE_INFO *mi) {
   int i, j;
-  MODE_INFO *ptr;
 
   // For each in image mode_info element set the in image flag to 1
-  for (i = 0; i < cpi->mi_rows; i++) {
-    ptr = mi;
-    for (j = 0; j < cpi->mi_cols; j++) {
+  for (i = 0; i < cm->mi_rows; i++) {
+    MODE_INFO *ptr = mi;
+    for (j = 0; j < cm->mi_cols; j++) {
       ptr->mbmi.mb_in_image = 1;
       ptr++;  // Next element in the row
     }
 
     // Step over border element at start of next row
-    mi += cpi->mode_info_stride;
+    mi += cm->mode_info_stride;
   }
 }
 
@@ -69,23 +67,46 @@
   oci->above_seg_context = 0;
 }
 
+static void set_mb_mi(VP9_COMMON *cm, int aligned_width, int aligned_height) {
+  cm->mb_cols = aligned_width >> 4;
+  cm->mb_rows = aligned_height >> 4;
+  cm->MBs = cm->mb_rows * cm->mb_cols;
+
+  cm->mi_cols = aligned_width >> LOG2_MI_SIZE;
+  cm->mi_rows = aligned_height >> LOG2_MI_SIZE;
+  cm->mode_info_stride = cm->mi_cols + 1;
+}
+
+static void setup_mi(VP9_COMMON *cm) {
+  cm->mi = cm->mip + cm->mode_info_stride + 1;
+  cm->prev_mi = cm->prev_mip + cm->mode_info_stride + 1;
+
+  vpx_memset(cm->mip, 0,
+             cm->mode_info_stride * (cm->mi_rows + 1) * sizeof(MODE_INFO));
+
+  vp9_update_mode_info_border(cm, cm->mip);
+  vp9_update_mode_info_in_image(cm, cm->mi);
+
+  vp9_update_mode_info_border(cm, cm->prev_mip);
+  vp9_update_mode_info_in_image(cm, cm->prev_mi);
+}
+
 int vp9_alloc_frame_buffers(VP9_COMMON *oci, int width, int height) {
   int i, mi_cols;
 
   // Our internal buffers are always multiples of 16
   const int aligned_width = multiple16(width);
   const int aligned_height = multiple16(height);
+  const int ss_x = oci->subsampling_x;
+  const int ss_y = oci->subsampling_y;
 
   vp9_free_frame_buffers(oci);
 
   for (i = 0; i < NUM_YV12_BUFFERS; i++) {
     oci->fb_idx_ref_cnt[i] = 0;
-    if (vp9_alloc_frame_buffer(&oci->yv12_fb[i], width, height,
-                               oci->subsampling_x, oci->subsampling_y,
-                               VP9BORDERINPIXELS) < 0) {
-      vp9_free_frame_buffers(oci);
-      return 1;
-    }
+    if (vp9_alloc_frame_buffer(&oci->yv12_fb[i], width, height, ss_x, ss_y,
+                               VP9BORDERINPIXELS) < 0)
+      goto fail;
   }
 
   oci->new_fb_idx = NUM_YV12_BUFFERS - 1;
@@ -99,77 +120,56 @@
     oci->fb_idx_ref_cnt[i] = 1;
   }
 
-  if (vp9_alloc_frame_buffer(&oci->temp_scale_frame, width, 16,
-                             oci->subsampling_x, oci->subsampling_y,
-                             VP9BORDERINPIXELS) < 0) {
-    vp9_free_frame_buffers(oci);
-    return 1;
-  }
+  if (vp9_alloc_frame_buffer(&oci->temp_scale_frame, width, 16, ss_x, ss_y,
+                             VP9BORDERINPIXELS) < 0)
+    goto fail;
 
-  if (vp9_alloc_frame_buffer(&oci->post_proc_buffer, width, height,
-                             oci->subsampling_x, oci->subsampling_y,
-                             VP9BORDERINPIXELS) < 0) {
-    vp9_free_frame_buffers(oci);
-    return 1;
-  }
+  if (vp9_alloc_frame_buffer(&oci->post_proc_buffer, width, height, ss_x, ss_y,
+                             VP9BORDERINPIXELS) < 0)
+    goto fail;
 
-  oci->mb_rows = aligned_height >> 4;
-  oci->mi_rows = aligned_height >> LOG2_MI_SIZE;
-  oci->mb_cols = aligned_width >> 4;
-  oci->mi_cols = aligned_width >> LOG2_MI_SIZE;
-  oci->MBs = oci->mb_rows * oci->mb_cols;
-  oci->mode_info_stride = oci->mi_cols + 1;
+  set_mb_mi(oci, aligned_width, aligned_height);
+
+  // Allocation
   oci->mip = vpx_calloc(oci->mode_info_stride * (oci->mi_rows + 1),
                         sizeof(MODE_INFO));
-
-  if (!oci->mip) {
-    vp9_free_frame_buffers(oci);
-    return 1;
-  }
-
-  oci->mi = oci->mip + oci->mode_info_stride + 1;
-
-  /* allocate memory for last frame MODE_INFO array */
+  if (!oci->mip)
+    goto fail;
 
   oci->prev_mip = vpx_calloc(oci->mode_info_stride * (oci->mi_rows + 1),
                              sizeof(MODE_INFO));
+  if (!oci->prev_mip)
+    goto fail;
 
-  if (!oci->prev_mip) {
-    vp9_free_frame_buffers(oci);
-    return 1;
-  }
-
-  oci->prev_mi = oci->prev_mip + oci->mode_info_stride + 1;
+  setup_mi(oci);
 
   // FIXME(jkoleszar): allocate subsampled arrays for U/V once subsampling
   // information is exposed at this level
   mi_cols = mi_cols_aligned_to_sb(oci);
+
+  // 2 contexts per 'mi unit', so that we have one context per 4x4 txfm
+  // block where mi unit size is 8x8.
 # if CONFIG_ALPHA
-  // TODO(jkoleszar): Why is this * 2?
   oci->above_context[0] = vpx_calloc(sizeof(ENTROPY_CONTEXT) * 8 * mi_cols, 1);
 #else
   oci->above_context[0] = vpx_calloc(sizeof(ENTROPY_CONTEXT) * 6 * mi_cols, 1);
 #endif
-  if (!oci->above_context[0]) {
-    vp9_free_frame_buffers(oci);
-    return 1;
-  }
+  if (!oci->above_context[0])
+    goto fail;
+
   for (i = 1; i < MAX_MB_PLANE; i++)
     oci->above_context[i] =
         oci->above_context[0] + i * sizeof(ENTROPY_CONTEXT) * 2 * mi_cols;
 
-  oci->above_seg_context =
-    vpx_calloc(sizeof(PARTITION_CONTEXT) * mi_cols, 1);
-
-  if (!oci->above_seg_context) {
-    vp9_free_frame_buffers(oci);
-    return 1;
-  }
-
-  vp9_update_mode_info_border(oci, oci->mip);
-  vp9_update_mode_info_in_image(oci, oci->mi);
+  oci->above_seg_context = vpx_calloc(sizeof(PARTITION_CONTEXT) * mi_cols, 1);
+  if (!oci->above_seg_context)
+    goto fail;
 
   return 0;
+
+ fail:
+  vp9_free_frame_buffers(oci);
+  return 1;
 }
 
 void vp9_setup_version(VP9_COMMON *cm) {
@@ -222,27 +222,10 @@
   vp9_entropy_mv_init();
 }
 
-
 void vp9_update_frame_size(VP9_COMMON *cm) {
   const int aligned_width = multiple16(cm->width);
   const int aligned_height = multiple16(cm->height);
 
-  cm->mb_rows = aligned_height >> 4;
-  cm->mb_cols = aligned_width >> 4;
-
-  cm->mi_rows = aligned_height >> LOG2_MI_SIZE;
-  cm->mi_cols = aligned_width >> LOG2_MI_SIZE;
-
-  cm->MBs = cm->mb_rows * cm->mb_cols;
-  cm->mode_info_stride = cm->mi_cols + 1;
-  cm->mi = cm->mip + cm->mode_info_stride + 1;
-  cm->prev_mi = cm->prev_mip + cm->mode_info_stride + 1;
-
-  memset(cm->mip, 0,
-         cm->mode_info_stride * (cm->mi_rows + 1) * sizeof(MODE_INFO));
-  vp9_update_mode_info_border(cm, cm->mip);
-  vp9_update_mode_info_in_image(cm, cm->mi);
-
-  vp9_update_mode_info_border(cm, cm->prev_mip);
-  vp9_update_mode_info_in_image(cm, cm->prev_mi);
+  set_mb_mi(cm, aligned_width, aligned_height);
+  setup_mi(cm);
 }
diff --git a/vp9/common/vp9_alloccommon.h b/vp9/common/vp9_alloccommon.h
index 814a760..fc79f63 100644
--- a/vp9/common/vp9_alloccommon.h
+++ b/vp9/common/vp9_alloccommon.h
@@ -14,6 +14,8 @@
 
 #include "vp9/common/vp9_onyxc_int.h"
 
+void vp9_initialize_common();
+
 void vp9_update_mode_info_border(VP9_COMMON *cpi, MODE_INFO *mi);
 void vp9_update_mode_info_in_image(VP9_COMMON *cpi, MODE_INFO *mi);
 
diff --git a/vp9/common/vp9_blockd.h b/vp9/common/vp9_blockd.h
index bc3416e..4b06a61 100644
--- a/vp9/common/vp9_blockd.h
+++ b/vp9/common/vp9_blockd.h
@@ -21,24 +21,26 @@
 #include "vp9/common/vp9_common.h"
 #include "vp9/common/vp9_enums.h"
 
+#define BLOCK_SIZE_GROUPS   4
 #define MAX_MB_SEGMENTS     8
 #define MB_SEG_TREE_PROBS   (MAX_MB_SEGMENTS-1)
-#define PREDICTION_PROBS 3
 
-#define DEFAULT_PRED_PROB_0 120
-#define DEFAULT_PRED_PROB_1 80
-#define DEFAULT_PRED_PROB_2 40
+#define PREDICTION_PROBS 3
 
 #define MBSKIP_CONTEXTS 3
 
 #define MAX_REF_LF_DELTAS       4
-#define MAX_MODE_LF_DELTAS      4
+#define MAX_MODE_LF_DELTAS      2
 
 /* Segment Feature Masks */
 #define SEGMENT_DELTADATA   0
 #define SEGMENT_ABSDATA     1
 #define MAX_MV_REF_CANDIDATES 2
 
+#define INTRA_INTER_CONTEXTS 4
+#define COMP_INTER_CONTEXTS 5
+#define REF_CONTEXTS 5
+
 typedef enum {
   PLANE_TYPE_Y_WITH_DC,
   PLANE_TYPE_UV,
@@ -55,7 +57,8 @@
 
 typedef enum {
   KEY_FRAME = 0,
-  INTER_FRAME = 1
+  INTER_FRAME = 1,
+  NUM_FRAME_TYPES,
 } FRAME_TYPE;
 
 typedef enum {
@@ -115,10 +118,19 @@
 
 #define VP9_INTRA_MODES (TM_PRED + 1)
 
-#define VP9_MVREFS (1 + NEWMV - NEARESTMV)
+#define VP9_INTER_MODES (1 + NEWMV - NEARESTMV)
 
 #define WHT_UPSCALE_FACTOR 2
 
+#define TX_SIZE_PROBS  6  // (TX_SIZE_MAX_SB * (TX_SIZE_MAX_SB - 1) / 2)
+
+#if TX_SIZE_PROBS == 6
+#define get_tx_probs_offset(b) ((b) < BLOCK_SIZE_MB16X16 ? 0 : \
+                                (b) < BLOCK_SIZE_SB32X32 ? 1 : 3)
+#else
+#define get_tx_probs_offset(b) 0
+#endif
+
 /* For keyframes, intra block modes are predicted by the (already decoded)
    modes for the Y blocks to the left and above us; for interframes, there
    is a single probability table. */
@@ -198,7 +210,7 @@
 
 typedef struct {
   MB_PREDICTION_MODE mode, uv_mode;
-  MV_REFERENCE_FRAME ref_frame, second_ref_frame;
+  MV_REFERENCE_FRAME ref_frame[2];
   TX_SIZE txfm_size;
   int_mv mv[2]; // for each reference frame used
   int_mv ref_mvs[MAX_REF_FRAMES][MAX_MV_REF_CANDIDATES];
@@ -213,7 +225,6 @@
 
   // Flags used for prediction status of various bistream signals
   unsigned char seg_id_predicted;
-  unsigned char ref_predicted;
 
   // Indicates if the mb is part of the image (1) vs border (0)
   // This can be useful in determining whether the MB provides
@@ -328,9 +339,9 @@
   signed char last_ref_lf_deltas[MAX_REF_LF_DELTAS];
   /* 0 = Intra, Last, GF, ARF */
   signed char ref_lf_deltas[MAX_REF_LF_DELTAS];
-  /* 0 = I4X4_PRED, ZERO_MV, MV, SPLIT */
+  /* 0 = ZERO_MV, MV */
   signed char last_mode_lf_deltas[MAX_MODE_LF_DELTAS];
-  /* 0 = I4X4_PRED, ZERO_MV, MV, SPLIT */
+  /* 0 = ZERO_MV, MV */
   signed char mode_lf_deltas[MAX_MODE_LF_DELTAS];
 
   /* Distance of MB away from frame edges */
@@ -524,7 +535,7 @@
   TX_TYPE tx_type;
   MODE_INFO *mi = xd->mode_info_context;
   MB_MODE_INFO *const mbmi = &mi->mbmi;
-  if (xd->lossless || mbmi->ref_frame != INTRA_FRAME)
+  if (xd->lossless || mbmi->ref_frame[0] != INTRA_FRAME)
     return DCT_DCT;
   if (mbmi->sb_type < BLOCK_SIZE_SB8X8) {
     tx_type = txfm_map(mi->bmi[ib].as_mode.first);
@@ -622,6 +633,7 @@
                                                   BLOCK_SIZE_TYPE bsize,
                                                   int ss_txfrm_size,
                                                   void *arg);
+
 static INLINE void foreach_transformed_block_in_plane(
     const MACROBLOCKD* const xd, BLOCK_SIZE_TYPE bsize, int plane,
     foreach_transformed_block_visitor visit, void *arg) {
@@ -630,14 +642,14 @@
   // block and transform sizes, in number of 4x4 blocks log 2 ("*_b")
   // 4x4=0, 8x8=2, 16x16=4, 32x32=6, 64x64=8
   // transform size varies per plane, look it up in a common way.
-  const TX_SIZE tx_size = plane ? get_uv_tx_size(xd)
-                                : xd->mode_info_context->mbmi.txfm_size;
+  const TX_SIZE tx_size =
+      plane ? get_uv_tx_size(xd) : xd->mode_info_context->mbmi.txfm_size;
   const int block_size_b = bw + bh;
   const int txfrm_size_b = tx_size * 2;
 
   // subsampled size of the block
-  const int ss_sum = xd->plane[plane].subsampling_x +
-                     xd->plane[plane].subsampling_y;
+  const int ss_sum = xd->plane[plane].subsampling_x
+      + xd->plane[plane].subsampling_y;
   const int ss_block_size = block_size_b - ss_sum;
 
   const int step = 1 << txfrm_size_b;
@@ -646,8 +658,42 @@
 
   assert(txfrm_size_b <= block_size_b);
   assert(txfrm_size_b <= ss_block_size);
-  for (i = 0; i < (1 << ss_block_size); i += step) {
-    visit(plane, i, bsize, txfrm_size_b, arg);
+
+  // If mb_to_right_edge is < 0 we are in a situation in which
+  // the current block size extends into the UMV and we won't
+  // visit the sub blocks that are wholly within the UMV.
+  if (xd->mb_to_right_edge < 0 || xd->mb_to_bottom_edge < 0) {
+    int r, c;
+    const int sw = bw - xd->plane[plane].subsampling_x;
+    const int sh = bh - xd->plane[plane].subsampling_y;
+    int max_blocks_wide = 1 << sw;
+    int max_blocks_high = 1 << sh;
+
+    // xd->mb_to_right_edge is in units of pixels * 8.  This converts
+    // it to 4x4 block sizes.
+    if (xd->mb_to_right_edge < 0)
+      max_blocks_wide +=
+          + (xd->mb_to_right_edge >> (5 + xd->plane[plane].subsampling_x));
+
+    if (xd->mb_to_bottom_edge < 0)
+      max_blocks_high +=
+          + (xd->mb_to_bottom_edge >> (5 + xd->plane[plane].subsampling_y));
+
+    i = 0;
+    // Unlike the normal case - in here we have to keep track of the
+    // row and column of the blocks we use so that we know if we are in
+    // the unrestricted motion border..
+    for (r = 0; r < (1 << sh); r += (1 << tx_size)) {
+      for (c = 0; c < (1 << sw); c += (1 << tx_size)) {
+        if (r < max_blocks_high && c < max_blocks_wide)
+          visit(plane, i, bsize, txfrm_size_b, arg);
+        i += step;
+      }
+    }
+  } else {
+    for (i = 0; i < (1 << ss_block_size); i += step) {
+      visit(plane, i, bsize, txfrm_size_b, arg);
+    }
   }
 }
 
@@ -779,4 +825,89 @@
   *x = (raster_mb & (tx_cols - 1)) << (txwl);
   *y = raster_mb >> tx_cols_lg2 << (txwl);
 }
+
+static void extend_for_intra(MACROBLOCKD* const xd, int plane, int block,
+                             BLOCK_SIZE_TYPE bsize, int ss_txfrm_size) {
+  const int bw = plane_block_width(bsize, &xd->plane[plane]);
+  const int bh = plane_block_height(bsize, &xd->plane[plane]);
+  int x, y;
+  txfrm_block_to_raster_xy(xd, bsize, plane, block, ss_txfrm_size, &x, &y);
+  x = x * 4 - 1;
+  y = y * 4 - 1;
+  // Copy a pixel into the umv if we are in a situation where the block size
+  // extends into the UMV.
+  // TODO(JBB): Should be able to do the full extend in place so we don't have
+  // to do this multiple times.
+  if (xd->mb_to_right_edge < 0) {
+    int umv_border_start = bw
+        + (xd->mb_to_right_edge >> (3 + xd->plane[plane].subsampling_x));
+
+    if (x + bw > umv_border_start)
+      vpx_memset(
+          xd->plane[plane].dst.buf + y * xd->plane[plane].dst.stride
+              + umv_border_start,
+          *(xd->plane[plane].dst.buf + y * xd->plane[plane].dst.stride
+              + umv_border_start - 1),
+          bw);
+  }
+  if (xd->mb_to_bottom_edge < 0) {
+    int umv_border_start = bh
+        + (xd->mb_to_bottom_edge >> (3 + xd->plane[plane].subsampling_y));
+    int i;
+    uint8_t c = *(xd->plane[plane].dst.buf
+        + (umv_border_start - 1) * xd->plane[plane].dst.stride + x);
+
+    uint8_t *d = xd->plane[plane].dst.buf
+        + umv_border_start * xd->plane[plane].dst.stride + x;
+
+    if (y + bh > umv_border_start)
+      for (i = 0; i < bh; i++, d += xd->plane[plane].dst.stride)
+        *d = c;
+  }
+}
+static void set_contexts_on_border(MACROBLOCKD *xd, BLOCK_SIZE_TYPE bsize,
+                                   int plane, int ss_tx_size, int eob, int aoff,
+                                   int loff, ENTROPY_CONTEXT *A,
+                                   ENTROPY_CONTEXT *L) {
+  const int bw = b_width_log2(bsize), bh = b_height_log2(bsize);
+  const int sw = bw - xd->plane[plane].subsampling_x;
+  const int sh = bh - xd->plane[plane].subsampling_y;
+  int mi_blocks_wide = 1 << sw;
+  int mi_blocks_high = 1 << sh;
+  int tx_size_in_blocks = (1 << ss_tx_size);
+  int above_contexts = tx_size_in_blocks;
+  int left_contexts = tx_size_in_blocks;
+  int pt;
+
+  // xd->mb_to_right_edge is in units of pixels * 8.  This converts
+  // it to 4x4 block sizes.
+  if (xd->mb_to_right_edge < 0) {
+    mi_blocks_wide += (xd->mb_to_right_edge
+        >> (5 + xd->plane[plane].subsampling_x));
+  }
+
+  // this code attempts to avoid copying into contexts that are outside
+  // our border.  Any blocks that do are set to 0...
+  if (above_contexts + aoff > mi_blocks_wide)
+    above_contexts = mi_blocks_wide - aoff;
+
+  if (xd->mb_to_bottom_edge < 0) {
+    mi_blocks_high += (xd->mb_to_bottom_edge
+        >> (5 + xd->plane[plane].subsampling_y));
+  }
+  if (left_contexts + loff > mi_blocks_high) {
+    left_contexts = mi_blocks_high - loff;
+  }
+
+  for (pt = 0; pt < above_contexts; pt++)
+    A[pt] = eob > 0;
+  for (pt = above_contexts; pt < (1 << ss_tx_size); pt++)
+    A[pt] = 0;
+  for (pt = 0; pt < left_contexts; pt++)
+    L[pt] = eob > 0;
+  for (pt = left_contexts; pt < (1 << ss_tx_size); pt++)
+    L[pt] = 0;
+}
+
+
 #endif  // VP9_COMMON_VP9_BLOCKD_H_
diff --git a/vp9/common/vp9_coefupdateprobs.h b/vp9/common/vp9_coefupdateprobs.h
index e862008..ce35634 100644
--- a/vp9/common/vp9_coefupdateprobs.h
+++ b/vp9/common/vp9_coefupdateprobs.h
@@ -14,6 +14,8 @@
 /* Update probabilities for the nodes in the token entropy tree.
    Generated file included by vp9_entropy.c */
 
+#define VP9_DEF_UPDATE_PROB 252
+
 static const vp9_prob vp9_coef_update_prob[UNCONSTRAINED_NODES] = {
   252, 252, 252,
 };
diff --git a/vp9/common/vp9_entropymode.c b/vp9/common/vp9_entropymode.c
index 0274b4d..bf57e7e 100644
--- a/vp9/common/vp9_entropymode.c
+++ b/vp9/common/vp9_entropymode.c
@@ -15,58 +15,87 @@
 #include "vp9/common/vp9_alloccommon.h"
 #include "vpx_mem/vpx_mem.h"
 
-static const unsigned int y_mode_cts[VP9_INTRA_MODES] = {
-  /* DC V  H D45 D135 D117 D153 D27 D63 TM */
-  98, 19, 15, 14, 14, 14, 14, 12, 12, 13,
+static const vp9_prob default_kf_uv_probs[VP9_INTRA_MODES]
+                                         [VP9_INTRA_MODES - 1] = {
+  { 149,  13,  48, 141, 174, 131,  54,  61, 109 } /* y = dc */,
+  { 120,  17, 119, 132, 103, 103,  54, 100, 130 } /* y = v */,
+  { 114,  16,  19, 177, 220, 145,  31,  33, 122 } /* y = h */,
+  { 119,  12,  43, 102, 133, 133,  77,  90, 102 } /* y = d45 */,
+  { 110,  10,  28, 144,  78, 158,  40,  49, 161 } /* y = d135 */,
+  { 114,  10,  46, 169,  50,  96,  48,  70, 150 } /* y = d117 */,
+  { 116,  10,  24, 125, 134, 168,  26,  27, 193 } /* y = d153 */,
+  { 121,  14,  26, 124, 175, 143,  36,  37,  79 } /* y = d27 */,
+  { 116,  13,  54, 100, 105, 122,  58, 126, 122 } /* y = d63 */,
+  {  98,  22,  60, 147, 159, 124,  45,  68, 128 } /* y = tm */
 };
 
-static const unsigned int uv_mode_cts[VP9_INTRA_MODES][VP9_INTRA_MODES] = {
-  /* DC   V   H  D45 135 117 153 D27 D63 TM */
-  { 200, 15, 15, 10, 10, 10, 10, 10, 10,  6}, /* DC */
-  { 130, 75, 10, 10, 10, 10, 10, 10, 10,  6}, /* V */
-  { 130, 10, 75, 10, 10, 10, 10, 10, 10,  6}, /* H */
-  { 130, 15, 10, 75, 10, 10, 10, 10, 10,  6}, /* D45 */
-  { 150, 15, 10, 10, 75, 10, 10, 10, 10,  6}, /* D135 */
-  { 150, 15, 10, 10, 10, 75, 10, 10, 10,  6}, /* D117 */
-  { 150, 15, 10, 10, 10, 10, 75, 10, 10,  6}, /* D153 */
-  { 150, 15, 10, 10, 10, 10, 10, 75, 10,  6}, /* D27 */
-  { 150, 15, 10, 10, 10, 10, 10, 10, 75,  6}, /* D63 */
-  { 160, 30, 30, 10, 10, 10, 10, 10, 10, 16}, /* TM */
+static const vp9_prob default_if_y_probs[BLOCK_SIZE_GROUPS]
+                                        [VP9_INTRA_MODES - 1] = {
+  {  42,  31,  23, 150, 161, 193,  32,  53, 100 } /* block_size < 8x8 */,
+  { 132,  58,  30, 160, 209, 195,  52,  47,  76 } /* block_size < 16x16 */,
+  { 179,  85,  24, 168, 236, 198,  87,  45,  46 } /* block_size < 32x32 */,
+  { 221, 176,  63, 133, 233, 121, 125, 105,  34 } /* block_size >= 32x32 */
 };
 
-static const unsigned int kf_uv_mode_cts[VP9_INTRA_MODES][VP9_INTRA_MODES] = {
-  // DC   V   H  D45 135 117 153 D27 D63 TM
-  { 160, 24, 24, 20, 20, 20, 20, 20, 20,  8}, /* DC */
-  { 102, 64, 30, 20, 20, 20, 20, 20, 20, 10}, /* V */
-  { 102, 30, 64, 20, 20, 20, 20, 20, 20, 10}, /* H */
-  { 102, 33, 20, 64, 20, 20, 20, 20, 20, 14}, /* D45 */
-  { 102, 33, 20, 20, 64, 20, 20, 20, 20, 14}, /* D135 */
-  { 122, 33, 20, 20, 20, 64, 20, 20, 20, 14}, /* D117 */
-  { 102, 33, 20, 20, 20, 20, 64, 20, 20, 14}, /* D153 */
-  { 102, 33, 20, 20, 20, 20, 20, 64, 20, 14}, /* D27 */
-  { 102, 33, 20, 20, 20, 20, 20, 20, 64, 14}, /* D63 */
-  { 132, 36, 30, 20, 20, 20, 20, 20, 20, 18}, /* TM */
+static const vp9_prob default_if_uv_probs[VP9_INTRA_MODES]
+                                         [VP9_INTRA_MODES - 1] = {
+  { 115,   7,  78, 180, 210, 127,  34,  57, 104 } /* y = dc */,
+  {  43,   9, 165, 140, 112,  93,  45, 125, 117 } /* y = v */,
+  {  68,   6,  25, 206, 241, 154,  16,  23, 102 } /* y = h */,
+  {  90,   5,  48, 117, 155, 134,  61,  88,  96 } /* y = d45 */,
+  {  77,   5,  43, 148, 100, 147,  37,  60, 146 } /* y = d135 */,
+  {  75,   5,  57, 167,  62,  91,  45,  76, 139 } /* y = d117 */,
+  {  86,   4,  34, 155, 185, 163,  22,  29, 160 } /* y = d153 */,
+  {  82,   5,  34, 155, 207, 144,  26,  38,  79 } /* y = d27 */,
+  {  69,   6,  65, 105, 104, 122,  48, 131, 116 } /* y = d63 */,
+  {  86,  16, 114, 177, 189, 108,  28,  72, 120 } /* y = tm */
 };
 
-const vp9_prob vp9_partition_probs[NUM_PARTITION_CONTEXTS]
+const vp9_prob vp9_partition_probs[NUM_FRAME_TYPES][NUM_PARTITION_CONTEXTS]
                                   [PARTITION_TYPES - 1] = {
-  // FIXME(jingning,rbultje) put real probabilities here
-  {202, 162, 107},
-  {16,  2,   169},
-  {3,   246,  19},
-  {104, 90,  134},
-  {202, 162, 107},
-  {16,  2,   169},
-  {3,   246,  19},
-  {104, 90,  134},
-  {202, 162, 107},
-  {16,  2,   169},
-  {3,   246,  19},
-  {104, 90,  134},
-  {183, 70,  109},
-  {30,  14,  162},
-  {67,  208,  22},
-  {4,   17,   5},
+  { /* frame_type = keyframe */
+    /* 8x8 -> 4x4 */
+    { 164, 121, 109 } /* a/l both not split */,
+    {  69,  11, 129 } /* a split, l not split */,
+    {  52, 181,  37 } /* l split, a not split */,
+    {  66,  71,  93 } /* a/l both split */,
+    /* 16x16 -> 8x8 */
+    { 154,  48,  43 } /* a/l both not split */,
+    {  81,  11,  63 } /* a split, l not split */,
+    {  67,  65,  17 } /* l split, a not split */,
+    {  57,  18,  24 } /* a/l both split */,
+    /* 32x32 -> 16x16 */
+    { 156,  42,  35 } /* a/l both not split */,
+    {  74,  10,  40 } /* a split, l not split */,
+    {  59,  53,  10 } /* l split, a not split */,
+    {  28,  10,   9 } /* a/l both split */,
+    /* 64x64 -> 32x32 */
+    { 168,  32,  43 } /* a/l both not split */,
+    {  59,  13,  41 } /* a split, l not split */,
+    {  60,  25,  10 } /* l split, a not split */,
+    {  13,   5,   4 } /* a/l both split */
+  }, { /* frame_type = interframe */
+    /* 8x8 -> 4x4 */
+    { 192, 121, 151 } /* a/l both not split */,
+    { 134,  63, 162 } /* a split, l not split */,
+    { 136, 134, 127 } /* l split, a not split */,
+    { 101,  97, 131 } /* a/l both split */,
+    /* 16x16 -> 8x8 */
+    { 167,  67,  80 } /* a/l both not split */,
+    {  87,  36,  70 } /* a split, l not split */,
+    {  90,  61,  45 } /* l split, a not split */,
+    {  46,  31,  32 } /* a/l both split */,
+    /* 32x32 -> 16x16 */
+    { 167,  63,  75 } /* a/l both not split */,
+    {  67,  27,  61 } /* a split, l not split */,
+    {  56,  87,  31 } /* l split, a not split */,
+    {  15,  13,  11 } /* a/l both split */,
+    /* 64x64 -> 32x32 */
+    { 222,  45,  44 } /* a/l both not split */,
+    {  62,  17,  62 } /* a split, l not split */,
+    {  52,  65,  16 } /* l split, a not split */,
+    {   9,   7,   6 } /* a/l both split */
+  }
 };
 
 /* Array indices are identical to previously-existing INTRAMODECONTEXTNODES. */
@@ -96,23 +125,85 @@
 
 struct vp9_token vp9_intra_mode_encodings[VP9_INTRA_MODES];
 
-struct vp9_token vp9_sb_mv_ref_encoding_array[VP9_MVREFS];
+struct vp9_token vp9_sb_mv_ref_encoding_array[VP9_INTER_MODES];
 
 struct vp9_token vp9_partition_encodings[PARTITION_TYPES];
 
+static const vp9_prob default_intra_inter_p[INTRA_INTER_CONTEXTS] = {
+  6, 87, 165, 213
+};
+
+static const vp9_prob default_comp_inter_p[COMP_INTER_CONTEXTS] = {
+  25, 66, 106, 142, 183
+};
+
+static const vp9_prob default_comp_ref_p[REF_CONTEXTS] = {
+  36, 93, 136, 205, 236
+};
+
+static const vp9_prob default_single_ref_p[REF_CONTEXTS][2] = {
+  { 30, 17 },
+  { 80, 66 },
+  { 142, 129 },
+  { 192, 178 },
+  { 235, 248 },
+};
+
+void tx_counts_to_branch_counts(unsigned int *tx_count_32x32p,
+                                unsigned int *tx_count_16x16p,
+                                unsigned int *tx_count_8x8p,
+                                unsigned int (*ct)[2]) {
+#if TX_SIZE_PROBS == 6
+  ct[0][0] = tx_count_8x8p[TX_4X4];
+  ct[0][1] = tx_count_8x8p[TX_8X8];
+  ct[1][0] = tx_count_16x16p[TX_4X4];
+  ct[1][1] = tx_count_16x16p[TX_8X8] + tx_count_16x16p[TX_16X16];
+  ct[2][0] = tx_count_16x16p[TX_8X8];
+  ct[2][1] = tx_count_16x16p[TX_16X16];
+  ct[3][0] = tx_count_32x32p[TX_4X4];
+  ct[3][1] = tx_count_32x32p[TX_8X8] + tx_count_32x32p[TX_16X16] +
+             tx_count_32x32p[TX_32X32];
+  ct[4][0] = tx_count_32x32p[TX_8X8];
+  ct[4][1] = tx_count_32x32p[TX_16X16] + tx_count_32x32p[TX_32X32];
+  ct[5][0] = tx_count_32x32p[TX_16X16];
+  ct[5][1] = tx_count_32x32p[TX_32X32];
+#else
+  ct[0][0] = tx_count_32x32p[TX_4X4] +
+             tx_count_16x16p[TX_4X4] +
+             tx_count_8x8p[TX_4X4];
+  ct[0][1] = tx_count_32x32p[TX_8X8] +
+             tx_count_32x32p[TX_16X16] +
+             tx_count_32x32p[TX_32X32] +
+             tx_count_16x16p[TX_8X8] +
+             tx_count_16x16p[TX_16X16] +
+             tx_count_8x8p[TX_8X8];
+  ct[1][0] = tx_count_32x32p[TX_8X8] +
+             tx_count_16x16p[TX_8X8];
+  ct[1][1] = tx_count_32x32p[TX_16X16] +
+             tx_count_32x32p[TX_32X32] +
+             tx_count_16x16p[TX_16X16];
+  ct[2][0] = tx_count_32x32p[TX_16X16];
+  ct[2][1] = tx_count_32x32p[TX_32X32];
+#endif
+}
+
+#if TX_SIZE_PROBS == 6
+const vp9_prob vp9_default_tx_probs[TX_SIZE_PROBS] = {
+  96, 96, 96, 96, 96, 96
+};
+#else
+const vp9_prob vp9_default_tx_probs[TX_SIZE_PROBS] = {
+  96, 96, 96
+};
+#endif
+
 void vp9_init_mbmode_probs(VP9_COMMON *x) {
-  unsigned int bct[VP9_INTRA_MODES][2];  // num Ymodes > num UV modes
-  int i;
-
-  vp9_tree_probs_from_distribution(vp9_intra_mode_tree, x->fc.y_mode_prob,
-                                   bct, y_mode_cts, 0);
-
-  for (i = 0; i < VP9_INTRA_MODES; i++) {
-    vp9_tree_probs_from_distribution(vp9_intra_mode_tree, x->kf_uv_mode_prob[i],
-                                     bct, kf_uv_mode_cts[i], 0);
-    vp9_tree_probs_from_distribution(vp9_intra_mode_tree, x->fc.uv_mode_prob[i],
-                                     bct, uv_mode_cts[i], 0);
-  }
+  vpx_memcpy(x->fc.uv_mode_prob, default_if_uv_probs,
+             sizeof(default_if_uv_probs));
+  vpx_memcpy(x->kf_uv_mode_prob, default_kf_uv_probs,
+             sizeof(default_kf_uv_probs));
+  vpx_memcpy(x->fc.y_mode_prob, default_if_y_probs,
+             sizeof(default_if_y_probs));
 
   vpx_memcpy(x->fc.switchable_interp_prob, vp9_switchable_interp_prob,
              sizeof(vp9_switchable_interp_prob));
@@ -120,9 +211,16 @@
   vpx_memcpy(x->fc.partition_prob, vp9_partition_probs,
              sizeof(vp9_partition_probs));
 
-  x->ref_pred_probs[0] = DEFAULT_PRED_PROB_0;
-  x->ref_pred_probs[1] = DEFAULT_PRED_PROB_1;
-  x->ref_pred_probs[2] = DEFAULT_PRED_PROB_2;
+  vpx_memcpy(x->fc.intra_inter_prob, default_intra_inter_p,
+             sizeof(default_intra_inter_p));
+  vpx_memcpy(x->fc.comp_inter_prob, default_comp_inter_p,
+             sizeof(default_comp_inter_p));
+  vpx_memcpy(x->fc.comp_ref_prob, default_comp_ref_p,
+             sizeof(default_comp_ref_p));
+  vpx_memcpy(x->fc.single_ref_prob, default_single_ref_p,
+             sizeof(default_single_ref_p));
+  vpx_memcpy(x->fc.tx_probs, vp9_default_tx_probs,
+             sizeof(vp9_default_tx_probs));
 }
 
 #if VP9_SWITCHABLE_FILTERS == 3
@@ -169,29 +267,30 @@
 }
 
 void vp9_init_mode_contexts(VP9_COMMON *pc) {
-  vpx_memset(pc->fc.mv_ref_ct, 0, sizeof(pc->fc.mv_ref_ct));
-  vpx_memcpy(pc->fc.vp9_mode_contexts,
-             vp9_default_mode_contexts,
-             sizeof(vp9_default_mode_contexts));
+  vpx_memset(pc->fc.inter_mode_counts, 0, sizeof(pc->fc.inter_mode_counts));
+  vpx_memcpy(pc->fc.inter_mode_probs,
+             vp9_default_inter_mode_probs,
+             sizeof(vp9_default_inter_mode_probs));
 }
 
 void vp9_accum_mv_refs(VP9_COMMON *pc,
                        MB_PREDICTION_MODE m,
                        const int context) {
-  unsigned int (*mv_ref_ct)[VP9_MVREFS - 1][2] = pc->fc.mv_ref_ct;
+  unsigned int (*inter_mode_counts)[VP9_INTER_MODES - 1][2] =
+      pc->fc.inter_mode_counts;
 
   if (m == ZEROMV) {
-    ++mv_ref_ct[context][0][0];
+    ++inter_mode_counts[context][0][0];
   } else {
-    ++mv_ref_ct[context][0][1];
+    ++inter_mode_counts[context][0][1];
     if (m == NEARESTMV) {
-      ++mv_ref_ct[context][1][0];
+      ++inter_mode_counts[context][1][0];
     } else {
-      ++mv_ref_ct[context][1][1];
+      ++inter_mode_counts[context][1][1];
       if (m == NEARMV) {
-        ++mv_ref_ct[context][2][0];
+        ++inter_mode_counts[context][2][0];
       } else {
-        ++mv_ref_ct[context][2][1];
+        ++inter_mode_counts[context][2][1];
       }
     }
   }
@@ -201,25 +300,35 @@
 #define MVREF_MAX_UPDATE_FACTOR 128
 void vp9_adapt_mode_context(VP9_COMMON *pc) {
   int i, j;
-  unsigned int (*mv_ref_ct)[VP9_MVREFS - 1][2] = pc->fc.mv_ref_ct;
-  int (*mode_context)[VP9_MVREFS - 1] = pc->fc.vp9_mode_contexts;
+  unsigned int (*inter_mode_counts)[VP9_INTER_MODES - 1][2] =
+      pc->fc.inter_mode_counts;
+  vp9_prob (*mode_context)[VP9_INTER_MODES - 1] = pc->fc.inter_mode_probs;
 
   for (j = 0; j < INTER_MODE_CONTEXTS; j++) {
-    for (i = 0; i < VP9_MVREFS - 1; i++) {
-      int count = mv_ref_ct[j][i][0] + mv_ref_ct[j][i][1], factor;
-
+    for (i = 0; i < VP9_INTER_MODES - 1; i++) {
+      int count = inter_mode_counts[j][i][0] + inter_mode_counts[j][i][1];
+      int factor;
       count = count > MVREF_COUNT_SAT ? MVREF_COUNT_SAT : count;
       factor = (MVREF_MAX_UPDATE_FACTOR * count / MVREF_COUNT_SAT);
-      mode_context[j][i] = weighted_prob(pc->fc.vp9_mode_contexts[j][i],
-                                         get_binary_prob(mv_ref_ct[j][i][0],
-                                                         mv_ref_ct[j][i][1]),
-                                         factor);
+      mode_context[j][i] = weighted_prob(
+          pc->fc.pre_inter_mode_probs[j][i],
+          get_binary_prob(inter_mode_counts[j][i][0],
+                          inter_mode_counts[j][i][1]),
+          factor);
     }
   }
 }
 
 #define MODE_COUNT_SAT 20
 #define MODE_MAX_UPDATE_FACTOR 144
+static int update_mode_ct(int pre_prob, int prob,
+                          unsigned int branch_ct[2]) {
+  int factor, count = branch_ct[0] + branch_ct[1];
+  count = count > MODE_COUNT_SAT ? MODE_COUNT_SAT : count;
+  factor = (MODE_MAX_UPDATE_FACTOR * count / MODE_COUNT_SAT);
+  return weighted_prob(pre_prob, prob, factor);
+}
+
 static void update_mode_probs(int n_modes,
                               const vp9_tree_index *tree, unsigned int *cnt,
                               vp9_prob *pre_probs, vp9_prob *dst_probs,
@@ -227,21 +336,22 @@
 #define MAX_PROBS 32
   vp9_prob probs[MAX_PROBS];
   unsigned int branch_ct[MAX_PROBS][2];
-  int t, count, factor;
+  int t;
 
   assert(n_modes - 1 < MAX_PROBS);
   vp9_tree_probs_from_distribution(tree, probs, branch_ct, cnt, tok0_offset);
-  for (t = 0; t < n_modes - 1; ++t) {
-    count = branch_ct[t][0] + branch_ct[t][1];
-    count = count > MODE_COUNT_SAT ? MODE_COUNT_SAT : count;
-    factor = (MODE_MAX_UPDATE_FACTOR * count / MODE_COUNT_SAT);
-    dst_probs[t] = weighted_prob(pre_probs[t], probs[t], factor);
-  }
+  for (t = 0; t < n_modes - 1; ++t)
+    dst_probs[t] = update_mode_ct(pre_probs[t], probs[t], branch_ct[t]);
+}
+
+static int update_mode_ct2(int pre_prob, unsigned int branch_ct[2]) {
+  return update_mode_ct(pre_prob, get_binary_prob(branch_ct[0],
+                                                  branch_ct[1]), branch_ct);
 }
 
 // #define MODE_COUNT_TESTING
 void vp9_adapt_mode_probs(VP9_COMMON *cm) {
-  int i;
+  int i, j;
   FRAME_CONTEXT *fc = &cm->fc;
 #ifdef MODE_COUNT_TESTING
   int t;
@@ -277,9 +387,24 @@
   printf("};\n");
 #endif
 
-  update_mode_probs(VP9_INTRA_MODES, vp9_intra_mode_tree,
-                    fc->y_mode_counts, fc->pre_y_mode_prob,
-                    fc->y_mode_prob, 0);
+  for (i = 0; i < INTRA_INTER_CONTEXTS; i++)
+    fc->intra_inter_prob[i] = update_mode_ct2(fc->pre_intra_inter_prob[i],
+                                              fc->intra_inter_count[i]);
+  for (i = 0; i < COMP_INTER_CONTEXTS; i++)
+    fc->comp_inter_prob[i] = update_mode_ct2(fc->pre_comp_inter_prob[i],
+                                             fc->comp_inter_count[i]);
+  for (i = 0; i < REF_CONTEXTS; i++)
+    fc->comp_ref_prob[i] = update_mode_ct2(fc->pre_comp_ref_prob[i],
+                                           fc->comp_ref_count[i]);
+  for (i = 0; i < REF_CONTEXTS; i++)
+    for (j = 0; j < 2; j++)
+      fc->single_ref_prob[i][j] = update_mode_ct2(fc->pre_single_ref_prob[i][j],
+                                                  fc->single_ref_count[i][j]);
+
+  for (i = 0; i < BLOCK_SIZE_GROUPS; i++)
+    update_mode_probs(VP9_INTRA_MODES, vp9_intra_mode_tree,
+                      fc->y_mode_counts[i], fc->pre_y_mode_prob[i],
+                      fc->y_mode_prob[i], 0);
 
   for (i = 0; i < VP9_INTRA_MODES; ++i)
     update_mode_probs(VP9_INTRA_MODES, vp9_intra_mode_tree,
@@ -289,7 +414,30 @@
   for (i = 0; i < NUM_PARTITION_CONTEXTS; i++)
     update_mode_probs(PARTITION_TYPES, vp9_partition_tree,
                       fc->partition_counts[i], fc->pre_partition_prob[i],
-                      fc->partition_prob[i], 0);
+                      fc->partition_prob[INTER_FRAME][i], 0);
+
+  if (cm->mcomp_filter_type == SWITCHABLE) {
+    for (i = 0; i <= VP9_SWITCHABLE_FILTERS; i++) {
+      update_mode_probs(VP9_SWITCHABLE_FILTERS, vp9_switchable_interp_tree,
+                        fc->switchable_interp_count[i],
+                        fc->pre_switchable_interp_prob[i],
+                        fc->switchable_interp_prob[i], 0);
+    }
+  }
+  if (cm->txfm_mode == TX_MODE_SELECT) {
+    unsigned int branch_ct[TX_SIZE_PROBS][2];
+    tx_counts_to_branch_counts(cm->fc.tx_count_32x32p,
+                               cm->fc.tx_count_16x16p,
+                               cm->fc.tx_count_8x8p, branch_ct);
+    for (i = 0; i < TX_SIZE_PROBS; ++i) {
+      int factor;
+      int count = branch_ct[i][0] + branch_ct[i][1];
+      vp9_prob prob = get_binary_prob(branch_ct[i][0], branch_ct[i][1]);
+      count = count > MODE_COUNT_SAT ? MODE_COUNT_SAT : count;
+      factor = (MODE_MAX_UPDATE_FACTOR * count / MODE_COUNT_SAT);
+      cm->fc.tx_probs[i] = weighted_prob(cm->fc.pre_tx_probs[i], prob, factor);
+    }
+  }
 }
 
 static void set_default_lf_deltas(MACROBLOCKD *xd) {
@@ -301,10 +449,8 @@
   xd->ref_lf_deltas[GOLDEN_FRAME] = -1;
   xd->ref_lf_deltas[ALTREF_FRAME] = -1;
 
-  xd->mode_lf_deltas[0] = 2;               // I4X4_PRED
-  xd->mode_lf_deltas[1] = -1;              // Zero
-  xd->mode_lf_deltas[2] = 1;               // New mv
-  xd->mode_lf_deltas[3] = 2;               // Split mv
+  xd->mode_lf_deltas[0] = 0;              // Zero
+  xd->mode_lf_deltas[1] = 0;               // New mv
 }
 
 void vp9_setup_past_independence(VP9_COMMON *cm, MACROBLOCKD *xd) {
diff --git a/vp9/common/vp9_entropymode.h b/vp9/common/vp9_entropymode.h
index b731560..ce13a4c 100644
--- a/vp9/common/vp9_entropymode.h
+++ b/vp9/common/vp9_entropymode.h
@@ -21,7 +21,7 @@
 
 extern const vp9_prob vp9_kf_default_bmode_probs[VP9_INTRA_MODES]
                                                 [VP9_INTRA_MODES]
-                                                [VP9_INTRA_MODES -1 ];
+                                                [VP9_INTRA_MODES - 1];
 
 extern const vp9_tree_index vp9_intra_mode_tree[];
 extern const vp9_tree_index  vp9_sb_mv_ref_tree[];
@@ -30,11 +30,14 @@
 
 /* Inter mode values do not start at zero */
 
-extern struct vp9_token vp9_sb_mv_ref_encoding_array[VP9_MVREFS];
+extern struct vp9_token vp9_sb_mv_ref_encoding_array[VP9_INTER_MODES];
 
 // probability models for partition information
 extern const vp9_tree_index  vp9_partition_tree[];
 extern struct vp9_token vp9_partition_encodings[PARTITION_TYPES];
+extern const vp9_prob vp9_partition_probs[NUM_FRAME_TYPES]
+                                         [NUM_PARTITION_CONTEXTS]
+                                         [PARTITION_TYPES - 1];
 
 void vp9_entropy_mode_init(void);
 
@@ -72,4 +75,11 @@
 extern const  vp9_prob vp9_switchable_interp_prob[VP9_SWITCHABLE_FILTERS + 1]
                                                  [VP9_SWITCHABLE_FILTERS - 1];
 
+extern const vp9_prob vp9_default_tx_probs[TX_SIZE_PROBS];
+
+extern void tx_counts_to_branch_counts(unsigned int *tx_count_32x32p,
+                                       unsigned int *tx_count_16x16p,
+                                       unsigned int *tx_count_8x8p,
+                                       unsigned int (*ct)[2]);
+
 #endif  // VP9_COMMON_VP9_ENTROPYMODE_H_
diff --git a/vp9/common/vp9_enums.h b/vp9/common/vp9_enums.h
index 7fb0d89..e18d353 100644
--- a/vp9/common/vp9_enums.h
+++ b/vp9/common/vp9_enums.h
@@ -16,8 +16,6 @@
 #define LOG2_MI_SIZE 3
 
 #define MI_SIZE (1 << LOG2_MI_SIZE)
-#define MI_UV_SIZE (1 << (LOG2_MI_SIZE - 1))
-
 #define MI_MASK ((64 >> LOG2_MI_SIZE) - 1)
 
 typedef enum BLOCK_SIZE_TYPE {
diff --git a/vp9/common/vp9_findnearmv.c b/vp9/common/vp9_findnearmv.c
index 9df6ce1..d781711 100644
--- a/vp9/common/vp9_findnearmv.c
+++ b/vp9/common/vp9_findnearmv.c
@@ -25,9 +25,9 @@
 }
 
 vp9_prob *vp9_mv_ref_probs(VP9_COMMON *pc, vp9_prob *p, int context) {
-  p[0] = pc->fc.vp9_mode_contexts[context][0];
-  p[1] = pc->fc.vp9_mode_contexts[context][1];
-  p[2] = pc->fc.vp9_mode_contexts[context][2];
+  p[0] = pc->fc.inter_mode_probs[context][0];
+  p[1] = pc->fc.inter_mode_probs[context][1];
+  p[2] = pc->fc.inter_mode_probs[context][2];
   return p;
 }
 
@@ -59,7 +59,7 @@
 
   vp9_find_mv_refs_idx(cm, xd, xd->mode_info_context,
                        xd->prev_mode_info_context,
-                       ref_idx ? mbmi->second_ref_frame : mbmi->ref_frame,
+                       mbmi->ref_frame[ref_idx],
                        mv_list, cm->ref_frame_sign_bias, block_idx);
 
   dst_list[1].as_int = 0;
diff --git a/vp9/common/vp9_findnearmv.h b/vp9/common/vp9_findnearmv.h
index 456d6c8..91736fe 100644
--- a/vp9/common/vp9_findnearmv.h
+++ b/vp9/common/vp9_findnearmv.h
@@ -71,7 +71,7 @@
 }
 
 vp9_prob *vp9_mv_ref_probs(VP9_COMMON *pc,
-                           vp9_prob p[VP9_MVREFS - 1],
+                           vp9_prob p[VP9_INTER_MODES - 1],
                            const int context);
 
 void vp9_append_sub8x8_mvs_for_idx(VP9_COMMON *pc,
@@ -87,7 +87,7 @@
     /* On L edge, get from MB to left of us */
     --cur_mb;
 
-    if (cur_mb->mbmi.ref_frame != INTRA_FRAME) {
+    if (cur_mb->mbmi.ref_frame[0] != INTRA_FRAME) {
       return DC_PRED;
     } else if (cur_mb->mbmi.sb_type < BLOCK_SIZE_SB8X8) {
       return ((cur_mb->bmi + 1 + b)->as_mode.first);
@@ -105,7 +105,7 @@
     /* On top edge, get from MB above us */
     cur_mb -= mi_stride;
 
-    if (cur_mb->mbmi.ref_frame != INTRA_FRAME) {
+    if (cur_mb->mbmi.ref_frame[0] != INTRA_FRAME) {
       return DC_PRED;
     } else if (cur_mb->mbmi.sb_type < BLOCK_SIZE_SB8X8) {
       return ((cur_mb->bmi + 2 + b)->as_mode.first);
diff --git a/vp9/common/vp9_implicit_segmentation.c b/vp9/common/vp9_implicit_segmentation.c
index a72c1c7..2a1d35f 100644
--- a/vp9/common/vp9_implicit_segmentation.c
+++ b/vp9/common/vp9_implicit_segmentation.c
@@ -140,11 +140,11 @@
           break;
         case SEGMENT_MV:
           n = mi[mb_index].mbmi.mv[0].as_int;
-          if (mi[mb_index].mbmi.ref_frame == INTRA_FRAME)
+          if (mi[mb_index].mbmi.ref_frame[0] == INTRA_FRAME)
             n = -9999999;
           break;
         case SEGMENT_REFFRAME:
-          n = mi[mb_index].mbmi.ref_frame;
+          n = mi[mb_index].mbmi.ref_frame[0];
           break;
         case SEGMENT_SKIPPED:
           n = mi[mb_index].mbmi.mb_skip_coeff;
diff --git a/vp9/common/vp9_loopfilter.c b/vp9/common/vp9_loopfilter.c
index eb7d01c..0347630 100644
--- a/vp9/common/vp9_loopfilter.c
+++ b/vp9/common/vp9_loopfilter.c
@@ -11,25 +11,26 @@
 #include "vpx_config.h"
 #include "vp9/common/vp9_loopfilter.h"
 #include "vp9/common/vp9_onyxc_int.h"
+#include "vp9/common/vp9_reconinter.h"
 #include "vpx_mem/vpx_mem.h"
 
 #include "vp9/common/vp9_seg_common.h"
 
 static void lf_init_lut(loop_filter_info_n *lfi) {
-  lfi->mode_lf_lut[DC_PRED] = 1;
-  lfi->mode_lf_lut[D45_PRED] = 1;
-  lfi->mode_lf_lut[D135_PRED] = 1;
-  lfi->mode_lf_lut[D117_PRED] = 1;
-  lfi->mode_lf_lut[D153_PRED] = 1;
-  lfi->mode_lf_lut[D27_PRED] = 1;
-  lfi->mode_lf_lut[D63_PRED] = 1;
-  lfi->mode_lf_lut[V_PRED] = 1;
-  lfi->mode_lf_lut[H_PRED] = 1;
-  lfi->mode_lf_lut[TM_PRED] = 1;
-  lfi->mode_lf_lut[ZEROMV]  = 1;
-  lfi->mode_lf_lut[NEARESTMV] = 2;
-  lfi->mode_lf_lut[NEARMV] = 2;
-  lfi->mode_lf_lut[NEWMV] = 2;
+  lfi->mode_lf_lut[DC_PRED] = 0;
+  lfi->mode_lf_lut[D45_PRED] = 0;
+  lfi->mode_lf_lut[D135_PRED] = 0;
+  lfi->mode_lf_lut[D117_PRED] = 0;
+  lfi->mode_lf_lut[D153_PRED] = 0;
+  lfi->mode_lf_lut[D27_PRED] = 0;
+  lfi->mode_lf_lut[D63_PRED] = 0;
+  lfi->mode_lf_lut[V_PRED] = 0;
+  lfi->mode_lf_lut[H_PRED] = 0;
+  lfi->mode_lf_lut[TM_PRED] = 0;
+  lfi->mode_lf_lut[ZEROMV]  = 0;
+  lfi->mode_lf_lut[NEARESTMV] = 1;
+  lfi->mode_lf_lut[NEARMV] = 1;
+  lfi->mode_lf_lut[NEWMV] = 1;
 }
 
 void vp9_loop_filter_update_sharpness(loop_filter_info_n *lfi,
@@ -131,13 +132,7 @@
     /* Apply delta for reference frame */
     lvl_ref += xd->ref_lf_deltas[ref] << n_shift;
 
-    /* Apply delta for Intra modes */
-    mode = 0; /* I4X4_PRED */
-    /* Only the split mode I4X4_PRED has a further special case */
-    lvl_mode = lvl_ref + (xd->mode_lf_deltas[mode] << n_shift);
-    lfi->lvl[seg][ref][mode] = clamp(lvl_mode, 0, 63);
-
-    mode = 1; /* all the rest of Intra modes */
+    mode = 0; /* all the rest of Intra modes */
     lvl_mode = lvl_ref;
     lfi->lvl[seg][ref][mode] = clamp(lvl_mode, 0, 63);
 
@@ -149,7 +144,7 @@
       lvl_ref += xd->ref_lf_deltas[ref] << n_shift;
 
       /* Apply delta for Inter modes */
-      for (mode = 1; mode < 4; mode++) {
+      for (mode = 0; mode < MAX_MODE_LF_DELTAS; mode++) {
         lvl_mode = lvl_ref + (xd->mode_lf_deltas[mode] << n_shift);
         lfi->lvl[seg][ref][mode] = clamp(lvl_mode, 0, 63);
       }
@@ -157,6 +152,7 @@
   }
 }
 
+#if !CONFIG_NEW_LOOPFILTER
 // Determine if we should skip inner-MB loop filtering within a MB
 // The current condition is that the loop filtering is skipped only
 // the MB uses a prediction size of 16x16 and either 16x16 transform
@@ -177,8 +173,8 @@
   const MB_MODE_INFO *mbmi0 = &mip0->mbmi;
   const MB_MODE_INFO *mbmi1 = &mip1->mbmi;
   return mb_lf_skip(mbmi0) && mb_lf_skip(mbmi1) &&
-         mbmi0->ref_frame != INTRA_FRAME &&
-         mbmi1->ref_frame != INTRA_FRAME;
+         mbmi0->ref_frame[0] != INTRA_FRAME &&
+         mbmi1->ref_frame[0] != INTRA_FRAME;
 }
 
 static void lpf_mb(VP9_COMMON *cm, const MODE_INFO *mi,
@@ -191,7 +187,7 @@
   int mode = mi->mbmi.mode;
   int mode_index = lfi_n->mode_lf_lut[mode];
   int seg = mi->mbmi.segment_id;
-  int ref_frame = mi->mbmi.ref_frame;
+  MV_REFERENCE_FRAME ref_frame = mi->mbmi.ref_frame[0];
   int filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
 
   if (filter_level) {
@@ -537,3 +533,235 @@
     }
   }
 }
+
+#else
+static int build_lfi(const VP9_COMMON *cm, const MB_MODE_INFO *mbmi,
+                      struct loop_filter_info *lfi) {
+  const loop_filter_info_n *lfi_n = &cm->lf_info;
+  int mode = mbmi->mode;
+  int mode_index = lfi_n->mode_lf_lut[mode];
+  int seg = mbmi->segment_id;
+  int ref_frame = mbmi->ref_frame[0];
+  int filter_level = lfi_n->lvl[seg][ref_frame][mode_index];
+
+  if (filter_level) {
+    const int hev_index = filter_level >> 4;
+    lfi->mblim = lfi_n->mblim[filter_level];
+    lfi->blim = lfi_n->blim[filter_level];
+    lfi->lim = lfi_n->lim[filter_level];
+    lfi->hev_thr = lfi_n->hev_thr[hev_index];
+    return 1;
+  }
+  return 0;
+}
+
+static void filter_selectively_vert(uint8_t *s, int pitch,
+                                    unsigned int mask_16x16,
+                                    unsigned int mask_8x8,
+                                    unsigned int mask_4x4,
+                                    unsigned int mask_4x4_1,
+                                    const struct loop_filter_info *lfi) {
+  unsigned int mask;
+
+  for (mask = mask_16x16 | mask_8x8 | mask_4x4; mask; mask >>= 1) {
+    if (mask & 1) {
+      if (mask_16x16 & 1) {
+        vp9_mb_lpf_vertical_edge_w(s, pitch, lfi->mblim, lfi->lim,
+                                   lfi->hev_thr, 1);
+        assert(!(mask_8x8 & 1));
+        assert(!(mask_4x4 & 1));
+        assert(!(mask_4x4_1 & 1));
+      } else if (mask_8x8 & 1) {
+        vp9_mbloop_filter_vertical_edge(s, pitch, lfi->mblim, lfi->lim,
+                                        lfi->hev_thr, 1);
+        assert(!(mask_16x16 & 1));
+        assert(!(mask_4x4 & 1));
+      } else if (mask_4x4 & 1) {
+        vp9_loop_filter_vertical_edge(s, pitch, lfi->mblim, lfi->lim,
+                                      lfi->hev_thr, 1);
+        assert(!(mask_16x16 & 1));
+        assert(!(mask_8x8 & 1));
+      } else {
+        assert(0);
+      }
+
+      if (mask_4x4_1 & 1)
+        vp9_loop_filter_vertical_edge(s + 4, pitch, lfi->mblim, lfi->lim,
+                                      lfi->hev_thr, 1);
+    }
+    s += 8;
+    lfi++;
+    mask_16x16 >>= 1;
+    mask_8x8 >>= 1;
+    mask_4x4 >>= 1;
+    mask_4x4_1 >>= 1;
+  }
+}
+
+static void filter_selectively_horiz(uint8_t *s, int pitch,
+                                     unsigned int mask_16x16,
+                                     unsigned int mask_8x8,
+                                     unsigned int mask_4x4,
+                                     unsigned int mask_4x4_1,
+                                     int only_4x4_1,
+                                     const struct loop_filter_info *lfi) {
+  unsigned int mask;
+
+  for (mask = mask_16x16 | mask_8x8 | mask_4x4; mask; mask >>= 1) {
+    if (mask & 1) {
+      if (!only_4x4_1) {
+        if (mask_16x16 & 1) {
+          vp9_mb_lpf_horizontal_edge_w(s, pitch, lfi->mblim, lfi->lim,
+                                       lfi->hev_thr, 1);
+          assert(!(mask_8x8 & 1));
+          assert(!(mask_4x4 & 1));
+          assert(!(mask_4x4_1 & 1));
+        } else if (mask_8x8 & 1) {
+          vp9_mbloop_filter_horizontal_edge(s, pitch, lfi->mblim, lfi->lim,
+                                            lfi->hev_thr, 1);
+          assert(!(mask_16x16 & 1));
+          assert(!(mask_4x4 & 1));
+        } else if (mask_4x4 & 1) {
+          vp9_loop_filter_horizontal_edge(s, pitch, lfi->mblim, lfi->lim,
+                                          lfi->hev_thr, 1);
+          assert(!(mask_16x16 & 1));
+          assert(!(mask_8x8 & 1));
+        } else {
+          assert(0);
+        }
+      }
+
+      if (mask_4x4_1 & 1)
+        vp9_loop_filter_horizontal_edge(s + 4 * pitch, pitch, lfi->mblim,
+                                        lfi->lim, lfi->hev_thr, 1);
+    }
+    s += 8;
+    lfi++;
+    mask_16x16 >>= 1;
+    mask_8x8 >>= 1;
+    mask_4x4 >>= 1;
+    mask_4x4_1 >>= 1;
+  }
+}
+
+static void filter_block_plane(VP9_COMMON *cm, MACROBLOCKD *xd,
+                               int plane, int mi_row, int mi_col) {
+  const int ss_x = xd->plane[plane].subsampling_x;
+  const int row_step = 1 << xd->plane[plane].subsampling_y;
+  const int col_step = 1 << xd->plane[plane].subsampling_x;
+  struct buf_2d * const dst = &xd->plane[plane].dst;
+  uint8_t* const dst0 = dst->buf;
+  MODE_INFO* const mi0 = xd->mode_info_context;
+  unsigned int mask_16x16[64 / MI_SIZE] = {0};
+  unsigned int mask_8x8[64 / MI_SIZE] = {0};
+  unsigned int mask_4x4[64 / MI_SIZE] = {0};
+  unsigned int mask_4x4_1[64 / MI_SIZE] = {0};
+  struct loop_filter_info lfi[64 / MI_SIZE][64 / MI_SIZE];
+  int r, c;
+
+  for (r = 0; r < 64 / MI_SIZE && mi_row + r < cm->mi_rows; r += row_step) {
+    unsigned int mask_16x16_c = 0;
+    unsigned int mask_8x8_c = 0;
+    unsigned int mask_4x4_c = 0;
+    unsigned int border_mask;
+
+    // Determine the vertical edges that need filtering
+    for (c = 0; c < 64 / MI_SIZE && mi_col + c < cm->mi_cols; c += col_step) {
+      const MODE_INFO const *mi = xd->mode_info_context;
+      const MODE_INFO const *mi_above = xd->mode_info_context -
+          cm->mode_info_stride;
+      const int skip_above =
+          (r + mi_row > 0) ? mi_above[c].mbmi.mb_skip_coeff : 0;
+      const int skip_left =
+          (c + mi_col > 0) ? mi[c - 1].mbmi.mb_skip_coeff : 0;
+      const int skip_this = mi[c].mbmi.mb_skip_coeff;
+      const int skip_this_c = skip_this && skip_left;
+      const int skip_this_r = skip_this && skip_above;
+      const TX_SIZE tx_size = plane ? get_uv_tx_size(xd) : mi[c].mbmi.txfm_size;
+
+      // Filter level can vary per MI
+      if (!build_lfi(cm, &mi[c].mbmi,
+                     lfi[r] + (c >> xd->plane[plane].subsampling_x)))
+        continue;
+
+      // Build masks based on the transform size of each block
+      if (tx_size == TX_32X32) {
+        if (!skip_this_c && (c & 3) == 0)
+          mask_16x16_c |= 1 << (c >> ss_x);
+        if (!skip_this_r && (r & 3) == 0)
+          mask_16x16[r] |= 1 << (c >> ss_x);
+      } else if (tx_size == TX_16X16) {
+        if (!skip_this_c && (c & 1) == 0)
+          mask_16x16_c |= 1 << (c >> ss_x);
+        if (!skip_this_r && (r & 1) == 0)
+          mask_16x16[r] |= 1 << (c >> ss_x);
+      } else {
+        // force 8x8 filtering on 32x32 boundaries
+        if (!skip_this_c) {
+          if (tx_size == TX_8X8 || (c & 3) == 0)
+            mask_8x8_c |= 1 << (c >> ss_x);
+          else
+            mask_4x4_c |= 1 << (c >> ss_x);
+        }
+
+        if (!skip_this_r) {
+          if (tx_size == TX_8X8 || (r & 3) == 0)
+            mask_8x8[r] |= 1 << (c >> ss_x);
+          else
+            mask_4x4[r] |= 1 << (c >> ss_x);
+        }
+
+        if (!skip_this && tx_size < TX_8X8)
+          mask_4x4_1[r] |= 1 << (c >> ss_x);
+      }
+    }
+
+    // Disable filtering on the leftmost column
+    border_mask = ~(mi_col == 0);
+    filter_selectively_vert(dst->buf, dst->stride,
+                            mask_16x16_c & border_mask,
+                            mask_8x8_c & border_mask,
+                            mask_4x4_c & border_mask,
+                            mask_4x4_1[r], lfi[r]);
+    dst->buf += 8 * dst->stride;
+    xd->mode_info_context += cm->mode_info_stride * row_step;
+  }
+
+  // Now do horizontal pass
+  dst->buf = dst0;
+  xd->mode_info_context = mi0;
+  for (r = 0; r < 64 / MI_SIZE && mi_row + r < cm->mi_rows; r += row_step) {
+    filter_selectively_horiz(dst->buf, dst->stride,
+                             mask_16x16[r],
+                             mask_8x8[r],
+                             mask_4x4[r],
+                             mask_4x4_1[r], mi_row + r == 0, lfi[r]);
+    dst->buf += 8 * dst->stride;
+    xd->mode_info_context += cm->mode_info_stride * row_step;
+  }
+}
+
+void vp9_loop_filter_frame(VP9_COMMON *cm,
+                           MACROBLOCKD *xd,
+                           int frame_filter_level,
+                           int y_only) {
+  int mi_row, mi_col;
+
+  // Initialize the loop filter for this frame.
+  vp9_loop_filter_frame_init(cm, xd, frame_filter_level);
+
+  for (mi_row = 0; mi_row < cm->mi_rows; mi_row += 64 / MI_SIZE) {
+    MODE_INFO* const mi = cm->mi + mi_row * cm->mode_info_stride;
+
+    for (mi_col = 0; mi_col < cm->mi_cols; mi_col += 64 / MI_SIZE) {
+      int plane;
+
+      setup_dst_planes(xd, cm->frame_to_show, mi_row, mi_col);
+      for (plane = 0; plane < (y_only ? 1 : MAX_MB_PLANE); plane++) {
+        xd->mode_info_context = mi + mi_col;
+        filter_block_plane(cm, xd, plane, mi_row, mi_col);
+      }
+    }
+  }
+}
+#endif
diff --git a/vp9/common/vp9_loopfilter_filters.c b/vp9/common/vp9_loopfilter_filters.c
index fc7fbc4..3f90304 100644
--- a/vp9/common/vp9_loopfilter_filters.c
+++ b/vp9/common/vp9_loopfilter_filters.c
@@ -206,6 +206,7 @@
   }
 }
 
+#if !CONFIG_NEW_LOOPFILTER
 /* Vertical MB Filtering */
 void vp9_loop_filter_mbv_c(uint8_t *y_ptr, uint8_t *u_ptr,
                            uint8_t *v_ptr, int y_stride, int uv_stride,
@@ -308,6 +309,7 @@
     vp9_loop_filter_vertical_edge_c(v + 4, uv_stride,
                                     lfi->blim, lfi->lim, lfi->hev_thr, 1);
 }
+#endif
 
 static INLINE void wide_mbfilter(int8_t mask, uint8_t hev,
                                  uint8_t flat, uint8_t flat2,
@@ -412,6 +414,7 @@
   }
 }
 
+#if !CONFIG_NEW_LOOPFILTER
 void vp9_lpf_mbv_w_c(uint8_t *y, uint8_t *u, uint8_t *v,
                      int y_stride, int uv_stride,
                      struct loop_filter_info *lfi) {
@@ -441,4 +444,4 @@
     vp9_mbloop_filter_horizontal_edge_c(v, uv_stride,
                                         lfi->mblim, lfi->lim, lfi->hev_thr, 1);
 }
-
+#endif
diff --git a/vp9/common/vp9_modecont.c b/vp9/common/vp9_modecont.c
index 973bb06..bdb0049 100644
--- a/vp9/common/vp9_modecont.c
+++ b/vp9/common/vp9_modecont.c
@@ -11,7 +11,8 @@
 
 #include "vp9/common/vp9_entropy.h"
 
-const int vp9_default_mode_contexts[INTER_MODE_CONTEXTS][VP9_MVREFS - 1] = {
+const vp9_prob vp9_default_inter_mode_probs[INTER_MODE_CONTEXTS]
+                                           [VP9_INTER_MODES - 1] = {
   {2,       173,   34},  // 0 = both zero mv
   {7,       145,   85},  // 1 = one zero mv + one a predicted mv
   {7,       166,   63},  // 2 = two predicted mvs
diff --git a/vp9/common/vp9_modecont.h b/vp9/common/vp9_modecont.h
index a6c4893..1a3e993 100644
--- a/vp9/common/vp9_modecont.h
+++ b/vp9/common/vp9_modecont.h
@@ -13,6 +13,7 @@
 
 #include "vp9/common/vp9_entropy.h"
 
-extern const int vp9_default_mode_contexts[INTER_MODE_CONTEXTS][VP9_MVREFS - 1];
+extern const int vp9_default_inter_mode_probs[INTER_MODE_CONTEXTS]
+                                             [VP9_INTER_MODES - 1];
 
 #endif  // VP9_COMMON_VP9_MODECONT_H_
diff --git a/vp9/common/vp9_modecontext.c b/vp9/common/vp9_modecontext.c
index 39d53f5..f50652a 100644
--- a/vp9/common/vp9_modecontext.c
+++ b/vp9/common/vp9_modecontext.c
@@ -13,116 +13,116 @@
 
 const vp9_prob vp9_kf_default_bmode_probs[VP9_INTRA_MODES]
                                          [VP9_INTRA_MODES]
-                                         [VP9_INTRA_MODES-1] = {
-  {  // Above 0
-    { 231,    9,  124,  138,   96,  200,   76,   42,   88, },  // left 0
-    { 152,   11,  187,  112,  170,  139,  130,   91,  113, },  // left 1
-    { 175,   10,   71,  182,  212,  191,   43,   39,   82, },  // left 2
-    {  56,   23,   63,   38,   76,   60,  185,  206,  159, },  // left 3
-    { 144,   52,   89,  192,   19,  236,  134,   93,   37, },  // left 4
-    { 114,   22,   29,  133,   37,   18,   60,  156,  233, },  // left 5
-    { 121,   16,   26,  124,  176,   50,   29,   20,  234, },  // left 6
-    { 170,   19,   50,   91,  169,  216,   14,   16,    5, },  // left 7
-    {  63,   14,   21,   68,   32,   29,   71,  224,  181, },  // left 8
-    {  81,   93,   62,   65,   78,  171,  152,  103,  172, },  // left 9
-  }, {  // Above 1
-    { 134,    2,  185,  147,  159,  152,   83,   33,  136, },  // left 0
-    {  72,    9,  194,  141,  208,  108,  124,   73,  119, },  // left 1
-    {  66,    1,  102,  183,  236,  151,   35,    8,   78, },  // left 2
-    {  41,   30,   60,   26,  101,  148,  212,  206,  177, },  // left 3
-    { 104,   91,  122,  184,   33,  243,  156,   73,    1, },  // left 4
-    {  74,   23,   47,  119,   63,   60,   79,  135,  211, },  // left 5
-    {  65,   12,   40,  134,  211,   79,   42,   37,  187, },  // left 6
-    {  87,   26,   76,   97,  218,  183,   27,    7,   31, },  // left 7
-    {  47,   24,   45,   53,   78,   89,  105,  215,  128, },  // left 8
-    {  66,   89,   68,   91,  120,  113,  190,  105,   98, },  // left 9
-  }, {  // Above 2
-    {  88,    1,   88,  166,  229,  115,   30,   23,  155, },  // left 0
-    {  43,    5,   98,  198,  244,  158,   50,   14,  113, },  // left 1
-    {  39,    1,   53,  208,  247,  208,   10,   11,   92, },  // left 2
-    {  56,   42,   41,  102,  156,  110,   76,   61,  106, },  // left 3
-    { 107,   79,   78,  158,   85,  255,   20,   64,  114, },  // left 4
-    {  39,   15,   30,  174,  135,   66,   85,   28,  176, },  // left 5
-    {  34,    5,   22,  137,  222,   64,   22,    5,  220, },  // left 6
-    {  68,    7,   25,  135,  206,  192,    7,   14,    8, },  // left 7
-    {  34,   45,   24,   78,   85,   55,   85,  120,   60, },  // left 8
-    {  62,   54,   23,  142,  182,  177,   64,   57,  171, },  // left 9
-  }, {  // Above 3
-    { 193,   15,  108,   82,  121,  192,  188,  119,  145, },  // left 0
-    {  60,   15,  157,   65,  142,   61,  202,  203,   85, },  // left 1
-    { 112,   17,  121,  128,  175,  128,   94,   85,    1, },  // left 2
-    {  40,   25,   47,   12,   20,   64,  221,  194,   57, },  // left 3
-    { 100,   74,  112,   85,   43,  255,   64,  142,  128, },  // left 4
-    {  88,   24,   47,   91,   93,   73,  141,  171,   85, },  // left 5
-    {  61,    9,   65,   75,  107,  146,   53,  100,  255, },  // left 6
-    { 142,    8,   80,  105,  199,  255,   20,   43,    1, },  // left 7
-    {  41,   17,   43,   22,   64,   43,   98,  246,  255, },  // left 8
-    {  51,   37,   59,   56,   94,   64,  200,  154,  128, },  // left 9
-  }, {  // Above 4
-    { 125,   10,  103,  129,   89,  209,   65,   22,   91, },  // left 0
-    {  95,   25,   93,  146,  108,  208,   96,   34,  108, },  // left 1
-    {  75,   17,   84,  185,  188,  199,   20,    1,   43, },  // left 2
-    {  57,   91,   27,   83,   23,  205,   67,   75,  149, },  // left 3
-    { 115,   70,   29,  237,    3,  247,   73,   51,    1, },  // left 4
-    {  38,   67,   45,   73,   64,   85,   51,   96,  255, },  // left 5
-    {  41,   25,   11,  142,  133,  128,   77,   73,  205, },  // left 6
-    { 101,   26,   32,  124,   38,  247,    7,    7,    8, },  // left 7
-    {  57,   91,   28,  128,   32,   73,  128,  128,  128, },  // left 8
-    { 117,  127,   39,  164,   51,  230,  128,  183,  255, },  // left 9
-  }, {  // Above 5
-    { 138,    5,   32,  135,   70,   29,   33,  115,  208, },  // left 0
-    {  67,    9,   91,  111,  142,   38,   78,   87,  199, },  // left 1
-    {  63,    7,   60,  172,  138,   60,   85,   64,  199, },  // left 2
-    {  40,   25,   44,   87,   71,   79,  102,  183,   85, },  // left 3
-    {  57,  110,   80,  140,   85,  255,   51,  128,  128, },  // left 4
-    {  47,   12,   16,  167,   26,   23,   69,  135,  171, },  // left 5
-    {  46,   14,   18,  102,   89,   15,    7,   67,  238, },  // left 6
-    {  65,    8,   33,  123,  158,   51,   18,   79,  114, },  // left 7
-    {  40,   16,    3,   91,   28,   32,   37,  207,  224, },  // left 8
-    {  87,   66,   49,   98,   32,  146,   59,   51,  224, },  // left 9
-  }, {  // Above 6
-    { 104,    1,   55,   88,  130,   39,    9,   17,  234, },  // left 0
-    {  64,   15,   96,  103,  192,   37,   43,   15,  248, },  // left 1
-    {  54,    2,   57,  135,  213,   70,    4,   22,  203, },  // left 2
-    {  30,   38,   40,   64,  128,   43,  114,  141,  171, },  // left 3
-    {  75,   43,   38,  181,   21,  233,  154,  128,    1, },  // left 4
-    {  39,    1,   19,  126,  107,   12,   35,   40,  237, },  // left 5
-    {  31,    6,    9,   77,  221,    1,    2,    4,  244, },  // left 6
-    {  88,   20,   33,   90,  110,  192,   39,   23,   51, },  // left 7
-    {  56,   21,   23,  119,   55,   70,   48,  177,  128, },  // left 8
-    {  55,   44,   46,  120,  188,    1,   60,   98,  192, },  // left 9
-  }, {  // Above 7
-    { 102,    1,   61,   95,  192,  205,    6,    9,   31, },  // left 0
-    {  69,   12,   63,  104,  187,  166,   14,    5,   20, },  // left 1
-    {  68,    1,   45,  136,  242,  154,    1,    7,   30, },  // left 2
-    {  62,   69,   24,   92,   73,  205,   82,   90,   93, },  // left 3
-    {  75,   31,   17,  215,   12,  246,   16,   17,    1, },  // left 4
-    {  37,   18,   46,  128,   80,   93,  112,    1,  114, },  // left 5
-    {  63,    9,   10,  125,  195,   85,   20,   11,  134, },  // left 6
-    {  86,    6,    6,   54,  136,  224,    1,    1,    1, },  // left 7
-    {  56,   24,    9,  110,   43,   77,  128,   96,    1, },  // left 8
-    {  58,   60,   20,   59,  116,  171,   69,   28,   75, },  // left 9
-  }, {  // Above 8
-    { 164,   10,   52,   70,  121,   74,  105,  168,  164, },  // left 0
-    {  51,   20,  112,   95,  138,   85,  101,  166,  238, },  // left 1
-    {  86,    9,   42,  122,  140,   77,  117,   39,   23, },  // left 2
-    {  22,   18,   28,   30,  156,  146,  141,  247,  255, },  // left 3
-    {  83,   98,   20,  128,   43,  205,  128,   85,    1, },  // left 4
-    {  45,   32,   18,   92,   67,   18,   38,  238,  255, },  // left 5
-    {  56,    7,   22,  104,   98,   32,   54,   85,  154, },  // left 6
-    {  85,   13,   27,  120,  192,  128,   57,   73,   51, },  // left 7
-    {  18,    7,   12,   29,   67,   37,   40,  240,  192, },  // left 8
-    {  35,   40,   32,   55,   57,   37,  147,  165,  154, },  // left 9
-  }, {  // Above 9
-    { 190,   31,   91,  133,   82,  229,  152,   59,  141, },  // left 0
-    {  85,   47,  155,  116,  163,  213,  141,   85,  171, },  // left 1
-    { 101,    8,   78,  184,  186,  142,  118,   37,  128, },  // left 2
-    {  56,   40,   49,   37,  128,  183,  219,  149,  205, },  // left 3
-    { 146,   92,   56,  184,   45,  229,  114,  102,    1, },  // left 4
-    {  71,   45,   37,  107,   51,   32,  110,  224,    1, },  // left 5
-    { 101,   26,   43,  111,  158,  102,   45,   91,  228, },  // left 6
-    { 138,   17,   48,  117,  144,  255,   81,   20,   21, },  // left 7
-    {  32,   33,   47,   64,   93,   73,  101,  179,  171, },  // left 8
-    { 112,  125,   38,  113,   56,  213,  168,  154,  192, },  // left 9
-  },
+                                         [VP9_INTRA_MODES - 1] = {
+  { /* above = dc */
+    { 165,  25,  57, 147, 137, 207,  70,  49,  89 } /* left = dc */,
+    { 107,  33, 127, 132, 131, 173,  86,  88, 105 } /* left = v */,
+    {  87,  25,  24, 193, 225, 213,  44,  33,  94 } /* left = h */,
+    {  82,  32,  42,  91, 116, 154, 134, 119, 110 } /* left = d45 */,
+    {  87,  41,  47, 164,  49, 219,  85,  72,  84 } /* left = d135 */,
+    {  83,  29,  29, 134,  55,  84,  58, 132, 185 } /* left = d117 */,
+    {  78,  22,  24, 134, 145, 161,  37,  32, 199 } /* left = d153 */,
+    { 103,  25,  33, 121, 156, 215,  34,  32,  29 } /* left = d27 */,
+    {  73,  28,  26,  91,  75, 116,  67, 169, 128 } /* left = d63 */,
+    {  62,  79,  46, 119, 142, 197,  97,  73, 133 } /* left = tm */
+  }, { /* above = v */
+    {  77,  19, 144, 147, 131, 159,  67,  75, 108 } /* left = dc */,
+    {  48,  30, 180, 135, 139, 124,  84, 125, 102 } /* left = v */,
+    {  47,  14,  76, 169, 216, 171,  48,  35,  77 } /* left = h */,
+    {  53,  39,  82,  93,  98, 165, 128, 156, 115 } /* left = d45 */,
+    {  59,  52,  88, 155,  54, 208,  95, 109,  23 } /* left = d135 */,
+    {  45,  30,  76, 136,  51,  95,  62, 154, 157 } /* left = d117 */,
+    {  45,  22,  60, 127, 136, 156,  45,  67, 157 } /* left = d153 */,
+    {  59,  30,  78, 107, 157, 181,  49,  39,  50 } /* left = d27 */,
+    {  45,  33,  70,  85,  76, 127,  76, 185,  89 } /* left = d63 */,
+    {  41,  69, 104, 113, 125, 154, 110, 123,  88 } /* left = tm */
+  }, { /* above = h */
+    {  85,  12,  38, 172, 219, 185,  40,  29, 118 } /* left = dc */,
+    {  52,  25,  78, 175, 211, 189,  56,  37, 108 } /* left = v */,
+    {  38,  11,  17, 207, 245, 224,  18,  13,  84 } /* left = h */,
+    {  63,  42,  25, 121, 162, 179,  63,  53,  90 } /* left = d45 */,
+    {  69,  59,  35, 146, 108, 245,  33,  56, 115 } /* left = d135 */,
+    {  45,  27,  30, 160, 118, 128,  75,  49, 147 } /* left = d117 */,
+    {  40,  17,  19, 147, 198, 169,  30,  14, 181 } /* left = d153 */,
+    {  56,  19,  15, 150, 207, 212,  17,  22,  28 } /* left = d27 */,
+    {  45,  50,  21,  97, 113, 135,  68,  89,  72 } /* left = d63 */,
+    {  41,  70,  19, 165, 199, 203,  54,  52, 121 } /* left = tm */
+  }, { /* above = d45 */
+    { 124,  25,  52, 122, 127, 200, 116,  88, 105 } /* left = dc */,
+    {  60,  31, 107, 103, 119, 136, 135, 150,  90 } /* left = v */,
+    {  70,  28,  37, 157, 203, 192,  73,  67,  21 } /* left = h */,
+    {  62,  33,  39,  54,  67, 159, 150, 114,  61 } /* left = d45 */,
+    {  69,  41,  46, 102,  64, 240,  68, 103, 111 } /* left = d135 */,
+    {  59,  27,  39, 121,  68, 132, 101, 139,  96 } /* left = d117 */,
+    {  55,  19,  33, 119, 109, 198,  61,  88, 224 } /* left = d153 */,
+    {  92,  16,  40, 107, 160, 242,  48,  62,  15 } /* left = d27 */,
+    {  57,  27,  36,  65,  95, 130,  94, 213, 222 } /* left = d63 */,
+    {  47,  47,  47, 101, 130, 154, 130, 105, 102 } /* left = tm */
+  }, { /* above = d135 */
+    {  80,  19,  42, 132,  81, 205,  51,  36,  99 } /* left = dc */,
+    {  60,  34,  67, 145,  76, 196,  72,  61, 112 } /* left = v */,
+    {  46,  25,  29, 172, 181, 208,  37,  11,  79 } /* left = h */,
+    {  59,  45,  20, 103,  42, 203,  57,  68, 107 } /* left = d45 */,
+    {  68,  41,  25, 190,  21, 226,  68,  65,  38 } /* left = d135 */,
+    {  42,  38,  34, 133,  48, 145,  57, 106, 237 } /* left = d117 */,
+    {  35,  20,  11, 139,  94, 197,  49,  50, 182 } /* left = d153 */,
+    {  64,  26,  24, 122,  73, 230,  27,  27,  39 } /* left = d27 */,
+    {  53,  49,  25, 118,  52, 147,  84, 104, 103 } /* left = d63 */,
+    {  62,  70,  35, 156,  90, 214,  95, 140, 211 } /* left = tm */
+  }, { /* above = d117 */
+    {  78,  14,  37, 152,  67, 100,  44, 103, 160 } /* left = dc */,
+    {  50,  20,  86, 139,  72,  98,  62, 111, 157 } /* left = v */,
+    {  42,  17,  33, 169, 153, 139,  62,  61, 136 } /* left = h */,
+    {  48,  21,  39, 123,  65, 143,  76, 131,  87 } /* left = d45 */,
+    {  47,  41,  44, 149,  49, 221,  51, 107, 122 } /* left = d135 */,
+    {  37,  18,  26, 177,  20,  66,  58, 131, 148 } /* left = d117 */,
+    {  39,  19,  26, 125,  77, 115,  22,  75, 192 } /* left = d153 */,
+    {  48,  13,  33, 125, 113, 132,  30,  77,  99 } /* left = d27 */,
+    {  45,  27,  15, 119,  42,  96,  45, 168, 164 } /* left = d63 */,
+    {  48,  52,  52, 129,  60, 158,  58,  89, 153 } /* left = tm */
+  }, { /* above = d153 */
+    {  82,   9,  31, 121, 146, 145,  23,  28, 194 } /* left = dc */,
+    {  57,  32,  78, 121, 148, 128,  50,  37, 217 } /* left = v */,
+    {  38,  12,  19, 158, 221, 172,  12,  22, 166 } /* left = h */,
+    {  49,  32,  24, 100, 125, 142,  72,  83, 132 } /* left = d45 */,
+    {  54,  36,  22, 172,  49, 225,  88,  72,  59 } /* left = d135 */,
+    {  43,   7,  23, 130,  95,  86,  44,  57, 206 } /* left = d117 */,
+    {  34,  13,  12,  90, 196,  91,   8,  10, 226 } /* left = d153 */,
+    {  55,  23,  17, 106, 127, 207,  32,  23,  92 } /* left = d27 */,
+    {  54,  28,  20, 121,  76, 151,  45, 110, 124 } /* left = d63 */,
+    {  41,  51,  31, 120, 192,  74,  45,  62, 163 } /* left = tm */
+  }, { /* above = d27 */
+    {  88,  10,  40, 120, 157, 211,  25,  27,  54 } /* left = dc */,
+    {  64,  31,  69, 121, 129, 184,  36,  29,  45 } /* left = v */,
+    {  51,  11,  22, 170, 232, 209,  11,  20,  64 } /* left = h */,
+    {  65,  43,  19, 102,  91, 208,  68,  78,  75 } /* left = d45 */,
+    {  64,  40,  23, 171,  47, 229,  45,  48,  19 } /* left = d135 */,
+    {  43,  27,  39, 136,  76, 149,  92,  13, 114 } /* left = d117 */,
+    {  53,  19,  14, 128, 148, 173,  31,  25, 133 } /* left = d153 */,
+    {  73,  19,  13,  97, 137, 218,  12,  12,  10 } /* left = d27 */,
+    {  57,  35,  15, 111,  68, 149,  90, 102,  16 } /* left = d63 */,
+    {  43,  63,  23, 107, 144, 200,  64,  47,  88 } /* left = tm */
+  }, { /* above = d63 */
+    {  95,  19,  44,  97, 120, 145,  81, 142, 115 } /* left = dc */,
+    {  46,  29,  93,  95, 106, 133,  83, 189, 177 } /* left = v */,
+    {  54,  19,  29, 136, 181, 157,  80,  67,  47 } /* left = h */,
+    {  44,  26,  34,  83, 125, 180, 116, 218, 206 } /* left = d45 */,
+    {  56,  41,  25, 118,  55, 192,  93, 121,  22 } /* left = d135 */,
+    {  44,  31,  30, 110,  67,  80,  56, 217, 225 } /* left = d117 */,
+    {  44,  14,  25, 101, 105, 136,  57,  83, 133 } /* left = d153 */,
+    {  62,  16,  28, 105, 157, 164,  67,  92,  58 } /* left = d27 */,
+    {  36,  18,  25,  57,  88, 113,  59, 210, 127 } /* left = d63 */,
+    {  36,  41,  44,  79, 104, 129, 100, 151, 105 } /* left = tm */
+  }, { /* above = tm */
+    {  90,  61,  68, 152, 141, 209,  79,  59,  93 } /* left = dc */,
+    {  49,  71, 127, 132, 129, 187,  89, 105, 113 } /* left = v */,
+    {  48,  29,  26, 190, 225, 190,  55,  32,  75 } /* left = h */,
+    {  58,  51,  46, 110, 134, 192, 124, 100, 113 } /* left = d45 */,
+    {  69,  60,  38, 156,  82, 214,  79,  89,  24 } /* left = d135 */,
+    {  48,  54,  50, 139,  71, 106,  77, 162,  18 } /* left = d117 */,
+    {  52,  34,  33, 137, 149, 184,  45,  67, 169 } /* left = d153 */,
+    {  67,  29,  32, 123, 176, 244,  47,  27,  31 } /* left = d27 */,
+    {  38,  43,  46,  93, 106, 140,  78, 143, 111 } /* left = d63 */,
+    {  55,  98,  50, 135, 140, 208,  95, 103,  95 } /* left = tm */
+  }
 };
diff --git a/vp9/common/vp9_mvref_common.c b/vp9/common/vp9_mvref_common.c
index f79d1c0..0a829d2 100644
--- a/vp9/common/vp9_mvref_common.c
+++ b/vp9/common/vp9_mvref_common.c
@@ -11,27 +11,34 @@
 #include "vp9/common/vp9_mvref_common.h"
 
 #define MVREF_NEIGHBOURS 8
-
-static int b_mv_ref_search[MVREF_NEIGHBOURS][2] = {
-  {0, -1}, {-1, 0}, {-1, -1}, {0, -2},
-  {-2, 0}, {-1, -2}, {-2, -1}, {-2, -2}
+static int mv_ref_blocks[BLOCK_SIZE_TYPES][MVREF_NEIGHBOURS][2] = {
+  // SB4X4
+  {{0, -1}, {-1, 0}, {-1, -1}, {0, -2}, {-2, 0}, {-1, -2}, {-2, -1}, {-2, -2}},
+  // SB4X8
+  {{0, -1}, {-1, 0}, {-1, -1}, {0, -2}, {-2, 0}, {-1, -2}, {-2, -1}, {-2, -2}},
+  // SB8X4
+  {{0, -1}, {-1, 0}, {-1, -1}, {0, -2}, {-2, 0}, {-1, -2}, {-2, -1}, {-2, -2}},
+  // SB8X8
+  {{0, -1}, {-1, 0}, {-1, -1}, {0, -2}, {-2, 0}, {-1, -2}, {-2, -1}, {-2, -2}},
+  // SB8X16
+  {{-1, 0}, {0, -1}, {-1, 1}, {-1, -1}, {-2, 0}, {0, -2}, {-1, -2}, {-2, -1}},
+  // SB16X8
+  {{0, -1}, {-1, 0}, {1, -1}, {-1, -1}, {0, -2}, {-2, 0}, {-2, -1}, {-1, -2}},
+  // SB16X16
+  {{0, -1}, {-1, 0}, {1, -1}, {-1, 1}, {-1, -1}, {0, -3}, {-3, 0}, {-3, -3}},
+  // SB16X32
+  {{-1, 0}, {0, -1}, {-1, 2}, {-1, -1}, {1, -1}, {-3, 0}, {0, -3}, {-3, -3}},
+  // SB32X16
+  {{0, -1}, {-1, 0}, {2, -1}, {-1, -1}, {-1, 1}, {0, -3}, {-3, 0}, {-3, -3}},
+  // SB32X32
+  {{1, -1}, {-1, 1}, {2, -1}, {-1, 2}, {-1, -1}, {0, -3}, {-3, 0}, {-3, -3}},
+  // SB32X64
+  {{-1, 0}, {0, -1}, {-1, 4}, {2, -1}, {-1, -1}, {-3, 0}, {0, -3}, {-1, 2}},
+  // SB64X32
+  {{0, -1}, {-1, 0}, {4, -1}, {-1, 2}, {-1, -1}, {0, -3}, {-3, 0}, {2, -1}},
+  // SB64X64
+  {{3, -1}, {-1, 3}, {4, -1}, {-1, 4}, {-1, -1}, {0, -1}, {-1, 0}, {6, -1}}
 };
-
-static int mb_mv_ref_search[MVREF_NEIGHBOURS][2] = {
-    {0, -1}, {-1, 0}, {-1, -1}, {0, -3},
-    {-3, 0}, {-1, -3}, {-3, -1}, {-3, -3}
-};
-
-static int sb_mv_ref_search[MVREF_NEIGHBOURS][2] = {
-    {0, -1}, {-1, 0}, {2, -1}, {-1, 2},
-    {-1, -1}, {0, -3}, {-3, 0}, {-1, -3}
-};
-
-static int sb64_mv_ref_search[MVREF_NEIGHBOURS][2] = {
-    {0, -1}, {-1, 0}, {2, -1}, {-1,  2},
-    {4, -1}, {-1, 4}, {6, -1}, {-1, -1}
-};
-
 // clamp_mv_ref
 #define MV_BORDER (16 << 3) // Allow 16 pels in 1/8th pel units
 
@@ -42,17 +49,17 @@
                                        xd->mb_to_bottom_edge + MV_BORDER);
 }
 
-// Gets a candidate refenence motion vector from the given mode info
+// Gets a candidate reference motion vector from the given mode info
 // structure if one exists that matches the given reference frame.
 static int get_matching_candidate(const MODE_INFO *candidate_mi,
                                   MV_REFERENCE_FRAME ref_frame,
                                   int_mv *c_mv, int block_idx) {
-  if (ref_frame == candidate_mi->mbmi.ref_frame) {
+  if (ref_frame == candidate_mi->mbmi.ref_frame[0]) {
     if (block_idx >= 0 && candidate_mi->mbmi.sb_type < BLOCK_SIZE_SB8X8)
       c_mv->as_int = candidate_mi->bmi[block_idx].as_mv[0].as_int;
     else
       c_mv->as_int = candidate_mi->mbmi.mv[0].as_int;
-  } else if (ref_frame == candidate_mi->mbmi.second_ref_frame) {
+  } else if (ref_frame == candidate_mi->mbmi.ref_frame[1]) {
     if (block_idx >= 0 && candidate_mi->mbmi.sb_type < BLOCK_SIZE_SB8X8)
       c_mv->as_int = candidate_mi->bmi[block_idx].as_mv[1].as_int;
     else
@@ -64,7 +71,7 @@
   return 1;
 }
 
-// Gets candidate refenence motion vector(s) from the given mode info
+// Gets candidate reference motion vector(s) from the given mode info
 // structure if they exists and do NOT match the given reference frame.
 static void get_non_matching_candidates(const MODE_INFO *candidate_mi,
                                         MV_REFERENCE_FRAME ref_frame,
@@ -79,18 +86,18 @@
   *c2_ref_frame = INTRA_FRAME;
 
   // If first candidate not valid neither will be.
-  if (candidate_mi->mbmi.ref_frame > INTRA_FRAME) {
+  if (candidate_mi->mbmi.ref_frame[0] > INTRA_FRAME) {
     // First candidate
-    if (candidate_mi->mbmi.ref_frame != ref_frame) {
-      *c_ref_frame = candidate_mi->mbmi.ref_frame;
+    if (candidate_mi->mbmi.ref_frame[0] != ref_frame) {
+      *c_ref_frame = candidate_mi->mbmi.ref_frame[0];
       c_mv->as_int = candidate_mi->mbmi.mv[0].as_int;
     }
 
     // Second candidate
-    if ((candidate_mi->mbmi.second_ref_frame > INTRA_FRAME) &&
-        (candidate_mi->mbmi.second_ref_frame != ref_frame) &&
+    if ((candidate_mi->mbmi.ref_frame[1] > INTRA_FRAME) &&
+        (candidate_mi->mbmi.ref_frame[1] != ref_frame) &&
         (candidate_mi->mbmi.mv[1].as_int != candidate_mi->mbmi.mv[0].as_int)) {
-      *c2_ref_frame = candidate_mi->mbmi.second_ref_frame;
+      *c2_ref_frame = candidate_mi->mbmi.ref_frame[1];
       c2_mv->as_int = candidate_mi->mbmi.mv[1].as_int;
     }
   }
@@ -154,25 +161,48 @@
   vpx_memset(mv_ref_list, 0, sizeof(int_mv) * MAX_MV_REF_CANDIDATES);
   vpx_memset(candidate_scores, 0, sizeof(candidate_scores));
 
-  if (mbmi->sb_type == BLOCK_SIZE_SB64X64) {
-    mv_ref_search = sb64_mv_ref_search;
-  } else if (mbmi->sb_type >= BLOCK_SIZE_SB32X32) {
-    mv_ref_search = sb_mv_ref_search;
-  } else if (mbmi->sb_type >= BLOCK_SIZE_MB16X16) {
-    mv_ref_search = mb_mv_ref_search;
-  } else {
-    mv_ref_search = b_mv_ref_search;
+  if (xd->mb_to_right_edge < 0 || xd->mb_to_bottom_edge < 0) {
+    int pixels_wide = 4 * b_width_log2(mbmi->sb_type);
+    int pixels_high = 4 * b_height_log2(mbmi->sb_type);
+    int pixels_square = 0;
+
+    if (xd->mb_to_right_edge < 0)
+      pixels_wide += (xd->mb_to_right_edge >> 3);
+
+    if (xd->mb_to_bottom_edge < 0)
+      pixels_high += (xd->mb_to_bottom_edge >> 3);
+
+    if ( pixels_wide < pixels_high )
+      pixels_square = pixels_wide;
+    else
+      pixels_square = pixels_high;
+
+    if (pixels_square == 64) {
+      mv_ref_search = mv_ref_blocks[BLOCK_SIZE_SB64X64];
+    } else if (pixels_square == 32) {
+      mv_ref_search = mv_ref_blocks[BLOCK_SIZE_SB32X32];
+    } else if (pixels_square == 16) {
+      mv_ref_search = mv_ref_blocks[BLOCK_SIZE_MB16X16];
+    } else {
+      mv_ref_search = mv_ref_blocks[BLOCK_SIZE_SB8X8];
+      if (mbmi->sb_type < BLOCK_SIZE_SB8X8) {
+        x_idx = block_idx & 1;
+        y_idx = block_idx >> 1;
+      }
+    }
+  }
+  else {
+  mv_ref_search = mv_ref_blocks[mbmi->sb_type];
     if (mbmi->sb_type < BLOCK_SIZE_SB8X8) {
       x_idx = block_idx & 1;
       y_idx = block_idx >> 1;
-    }
+      }
   }
 
   // We first scan for candidate vectors that match the current reference frame
   // Look at nearest neigbours
   for (i = 0; i < 2; ++i) {
     const int mi_search_col = mi_col + mv_ref_search[i][0];
-
     if ((mi_search_col >= cm->cur_tile_mi_col_start) &&
         (mi_search_col < cm->cur_tile_mi_col_end) &&
         ((mv_ref_search[i][1] << 6) >= xd->mb_to_top_edge)) {
@@ -194,7 +224,7 @@
                          &refmv_count, c_refmv, 16);
       }
       split_count += (candidate_mi->mbmi.sb_type < BLOCK_SIZE_SB8X8 &&
-                      candidate_mi->mbmi.ref_frame != INTRA_FRAME);
+                      candidate_mi->mbmi.ref_frame[0] != INTRA_FRAME);
 
       // Count number of neihgbours coded intra and zeromv
       intra_count += (candidate_mi->mbmi.mode < NEARESTMV);
diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h
index cbe010a..dedda20 100644
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -26,8 +26,6 @@
 
 /* Create/destroy static data structures. */
 
-void vp9_initialize_common(void);
-
 // Define the number of candidate reference buffers.
 #define NUM_REF_FRAMES 8
 #define NUM_REF_FRAMES_LG2 3
@@ -42,23 +40,22 @@
 #define NUM_FRAME_CONTEXTS_LG2 2
 #define NUM_FRAME_CONTEXTS (1 << NUM_FRAME_CONTEXTS_LG2)
 
-#define COMP_PRED_CONTEXTS   2
-
 #define MAX_LAG_BUFFERS 25
 
 typedef struct frame_contexts {
-  vp9_prob y_mode_prob[VP9_INTRA_MODES - 1]; /* interframe intra mode probs */
+  vp9_prob y_mode_prob[BLOCK_SIZE_GROUPS][VP9_INTRA_MODES - 1];
   vp9_prob uv_mode_prob[VP9_INTRA_MODES][VP9_INTRA_MODES - 1];
-  vp9_prob partition_prob[NUM_PARTITION_CONTEXTS][PARTITION_TYPES - 1];
+  vp9_prob partition_prob[NUM_FRAME_TYPES][NUM_PARTITION_CONTEXTS]
+                         [PARTITION_TYPES - 1];
 
   nmv_context nmvc;
   nmv_context pre_nmvc;
   /* interframe intra mode probs */
-  vp9_prob pre_y_mode_prob[VP9_INTRA_MODES - 1];
+  vp9_prob pre_y_mode_prob[BLOCK_SIZE_GROUPS][VP9_INTRA_MODES - 1];
   vp9_prob pre_uv_mode_prob[VP9_INTRA_MODES][VP9_INTRA_MODES - 1];
   vp9_prob pre_partition_prob[NUM_PARTITION_CONTEXTS][PARTITION_TYPES - 1];
   /* interframe intra mode probs */
-  unsigned int y_mode_counts[VP9_INTRA_MODES];
+  unsigned int y_mode_counts[BLOCK_SIZE_GROUPS][VP9_INTRA_MODES];
   unsigned int uv_mode_counts[VP9_INTRA_MODES][VP9_INTRA_MODES];
   unsigned int partition_counts[NUM_PARTITION_CONTEXTS][PARTITION_TYPES];
 
@@ -71,9 +68,32 @@
   nmv_context_counts NMVcount;
   vp9_prob switchable_interp_prob[VP9_SWITCHABLE_FILTERS + 1]
                                  [VP9_SWITCHABLE_FILTERS - 1];
+  vp9_prob pre_switchable_interp_prob[VP9_SWITCHABLE_FILTERS + 1]
+      [VP9_SWITCHABLE_FILTERS - 1];
+  unsigned int switchable_interp_count[VP9_SWITCHABLE_FILTERS + 1]
+                                      [VP9_SWITCHABLE_FILTERS];
 
-  int vp9_mode_contexts[INTER_MODE_CONTEXTS][VP9_MVREFS - 1];
-  unsigned int mv_ref_ct[INTER_MODE_CONTEXTS][VP9_MVREFS - 1][2];
+  vp9_prob inter_mode_probs[INTER_MODE_CONTEXTS][VP9_INTER_MODES - 1];
+  vp9_prob pre_inter_mode_probs[INTER_MODE_CONTEXTS][VP9_INTER_MODES - 1];
+  unsigned int inter_mode_counts[INTER_MODE_CONTEXTS][VP9_INTER_MODES - 1][2];
+
+  vp9_prob intra_inter_prob[INTRA_INTER_CONTEXTS];
+  vp9_prob comp_inter_prob[COMP_INTER_CONTEXTS];
+  vp9_prob single_ref_prob[REF_CONTEXTS][2];
+  vp9_prob comp_ref_prob[REF_CONTEXTS];
+  vp9_prob pre_intra_inter_prob[INTRA_INTER_CONTEXTS];
+  vp9_prob pre_comp_inter_prob[COMP_INTER_CONTEXTS];
+  vp9_prob pre_single_ref_prob[REF_CONTEXTS][2];
+  vp9_prob pre_comp_ref_prob[REF_CONTEXTS];
+  unsigned int intra_inter_count[INTRA_INTER_CONTEXTS][2];
+  unsigned int comp_inter_count[COMP_INTER_CONTEXTS][2];
+  unsigned int single_ref_count[REF_CONTEXTS][2][2];
+  unsigned int comp_ref_count[REF_CONTEXTS][2];
+  vp9_prob tx_probs[TX_SIZE_PROBS];
+  vp9_prob pre_tx_probs[TX_SIZE_PROBS];
+  unsigned int tx_count_32x32p[TX_SIZE_MAX_SB];
+  unsigned int tx_count_16x16p[TX_SIZE_MAX_SB - 1];
+  unsigned int tx_count_8x8p[TX_SIZE_MAX_SB - 2];
 } FRAME_CONTEXT;
 
 typedef enum {
@@ -158,7 +178,6 @@
   /* profile settings */
   int experimental;
   TXFM_MODE txfm_mode;
-  COMPPREDMODE_TYPE comp_pred_mode;
   int no_lpf;
   int use_bilinear_mc_filter;
 
@@ -215,23 +234,15 @@
                          [VP9_INTRA_MODES - 1];
   vp9_prob kf_uv_mode_prob[VP9_INTRA_MODES] [VP9_INTRA_MODES - 1];
 
-  vp9_prob prob_intra_coded;
-  vp9_prob prob_last_coded;
-  vp9_prob prob_gf_coded;
-
   // Context probabilities when using predictive coding of segment id
   vp9_prob segment_pred_probs[PREDICTION_PROBS];
   unsigned char temporal_update;
 
   // Context probabilities for reference frame prediction
-  unsigned char ref_scores[MAX_REF_FRAMES];
-  vp9_prob ref_pred_probs[PREDICTION_PROBS];
-  vp9_prob mod_refprobs[MAX_REF_FRAMES][PREDICTION_PROBS];
-
-  vp9_prob prob_comppred[COMP_PRED_CONTEXTS];
-
-  // FIXME contextualize
-  vp9_prob prob_tx[TX_SIZE_MAX_SB - 1];
+  int allow_comp_inter_inter;
+  MV_REFERENCE_FRAME comp_fixed_ref;
+  MV_REFERENCE_FRAME comp_var_ref[2];
+  COMPPREDMODE_TYPE comp_pred_mode;
 
   vp9_prob mbskip_pred_probs[MBSKIP_CONTEXTS];
 
@@ -243,9 +254,6 @@
   int near_boffset[3];
   int version;
 
-#ifdef PACKET_TESTING
-  VP9_HEADER oh;
-#endif
   double bitrate;
   double framerate;
 
diff --git a/vp9/common/vp9_pred_common.c b/vp9/common/vp9_pred_common.c
index 459e9d5..73c7278 100644
--- a/vp9/common/vp9_pred_common.c
+++ b/vp9/common/vp9_pred_common.c
@@ -26,6 +26,8 @@
   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;
+  const int left_in_image = xd->left_available && left_mi->mbmi.mb_in_image;
+  const int above_in_image = xd->up_available && above_mi->mbmi.mb_in_image;
   // Note:
   // The mode info data structure has a one element border above and to the
   // left of the entries correpsonding to real macroblocks.
@@ -37,19 +39,6 @@
         pred_context += left_mi->mbmi.seg_id_predicted;
       break;
 
-    case PRED_REF:
-      pred_context = above_mi->mbmi.ref_predicted;
-      if (xd->left_available)
-        pred_context += left_mi->mbmi.ref_predicted;
-      break;
-
-    case PRED_COMP:
-      if (mi->mbmi.ref_frame == LAST_FRAME)
-        pred_context = 0;
-      else
-        pred_context = 1;
-      break;
-
     case PRED_MBSKIP:
       pred_context = above_mi->mbmi.mb_skip_coeff;
       if (xd->left_available)
@@ -58,14 +47,12 @@
 
     case PRED_SWITCHABLE_INTERP: {
       // left
-      const int left_in_image = xd->left_available && left_mi->mbmi.mb_in_image;
       const int left_mv_pred = is_inter_mode(left_mi->mbmi.mode);
       const int left_interp = left_in_image && left_mv_pred ?
                     vp9_switchable_interp_map[left_mi->mbmi.interp_filter] :
                     VP9_SWITCHABLE_FILTERS;
 
       // above
-      const int above_in_image = xd->up_available && above_mi->mbmi.mb_in_image;
       const int above_mv_pred = is_inter_mode(above_mi->mbmi.mode);
       const int above_interp = above_in_image && above_mv_pred ?
                     vp9_switchable_interp_map[above_mi->mbmi.interp_filter] :
@@ -88,7 +75,281 @@
       break;
     }
 
+    case PRED_INTRA_INTER: {
+      if (above_in_image && left_in_image) {  // both edges available
+        if (left_mi->mbmi.ref_frame[0] == INTRA_FRAME &&
+            above_mi->mbmi.ref_frame[0] == INTRA_FRAME) {  // intra/intra (3)
+          pred_context = 3;
+        } else {  // intra/inter (1) or inter/inter (0)
+          pred_context = left_mi->mbmi.ref_frame[0] == INTRA_FRAME ||
+                         above_mi->mbmi.ref_frame[0] == INTRA_FRAME;
+        }
+      } else if (above_in_image || left_in_image) {  // one edge available
+        const MODE_INFO *edge = above_in_image ? above_mi : left_mi;
+
+        // inter: 0, intra: 2
+        pred_context = 2 * (edge->mbmi.ref_frame[0] == INTRA_FRAME);
+      } else {
+        pred_context = 0;
+      }
+      assert(pred_context >= 0 && pred_context < INTRA_INTER_CONTEXTS);
+      break;
+    }
+
+    case PRED_COMP_INTER_INTER: {
+      if (above_in_image && left_in_image) {  // both edges available
+        if (above_mi->mbmi.ref_frame[1] <= INTRA_FRAME &&
+            left_mi->mbmi.ref_frame[1] <= INTRA_FRAME) {
+          // neither edge uses comp pred (0/1)
+          pred_context = ((above_mi->mbmi.ref_frame[0] == cm->comp_fixed_ref) ^
+                          (left_mi->mbmi.ref_frame[0] == cm->comp_fixed_ref));
+        } else if (above_mi->mbmi.ref_frame[1] <= INTRA_FRAME) {
+          // one of two edges uses comp pred (2/3)
+          pred_context = 2 +
+              (above_mi->mbmi.ref_frame[0] == cm->comp_fixed_ref ||
+               above_mi->mbmi.ref_frame[0] == INTRA_FRAME);
+        } else if (left_mi->mbmi.ref_frame[1] <= INTRA_FRAME) {
+          // one of two edges uses comp pred (2/3)
+          pred_context = 2 +
+              (left_mi->mbmi.ref_frame[0] == cm->comp_fixed_ref ||
+               left_mi->mbmi.ref_frame[0] == INTRA_FRAME);
+        } else {  // both edges use comp pred (4)
+          pred_context = 4;
+        }
+      } else if (above_in_image || left_in_image) {  // one edge available
+        const MODE_INFO *edge = above_in_image ? above_mi : left_mi;
+
+        if (edge->mbmi.ref_frame[1] <= INTRA_FRAME) {
+          // edge does not use comp pred (0/1)
+          pred_context = edge->mbmi.ref_frame[0] == cm->comp_fixed_ref;
+        } else {  // edge uses comp pred (3)
+          pred_context = 3;
+        }
+      } else {  // no edges available (1)
+        pred_context = 1;
+      }
+      assert(pred_context >= 0 && pred_context < COMP_INTER_CONTEXTS);
+      break;
+    }
+
+    case PRED_COMP_REF_P: {
+      const int fix_ref_idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
+      const int var_ref_idx = !fix_ref_idx;
+
+      if (above_in_image && left_in_image) {  // both edges available
+        if (above_mi->mbmi.ref_frame[0] == INTRA_FRAME &&
+            left_mi->mbmi.ref_frame[0] == INTRA_FRAME) {  // intra/intra (2)
+          pred_context = 2;
+        } else if (above_mi->mbmi.ref_frame[0] == INTRA_FRAME ||
+                   left_mi->mbmi.ref_frame[0] == INTRA_FRAME) {  // intra/inter
+          const MODE_INFO *edge = above_mi->mbmi.ref_frame[0] == INTRA_FRAME ?
+                                  left_mi : above_mi;
+
+          if (edge->mbmi.ref_frame[1] <= INTRA_FRAME) {  // single pred (1/3)
+            pred_context = 1 +
+                2 * edge->mbmi.ref_frame[0] != cm->comp_var_ref[1];
+          } else {  // comp pred (1/3)
+            pred_context = 1 +
+                2 * edge->mbmi.ref_frame[var_ref_idx] != cm->comp_var_ref[1];
+          }
+        } else {  // inter/inter
+          int l_sg = left_mi->mbmi.ref_frame[1] <= INTRA_FRAME;
+          int a_sg = above_mi->mbmi.ref_frame[1] <= INTRA_FRAME;
+          MV_REFERENCE_FRAME vrfa = a_sg ? above_mi->mbmi.ref_frame[0] :
+              above_mi->mbmi.ref_frame[var_ref_idx];
+          MV_REFERENCE_FRAME vrfl = l_sg ? left_mi->mbmi.ref_frame[0] :
+              left_mi->mbmi.ref_frame[var_ref_idx];
+
+          if (vrfa == vrfl && cm->comp_var_ref[1] == vrfa) {
+            pred_context = 0;
+          } else if (l_sg && a_sg) {  // single/single
+            if ((vrfa == cm->comp_fixed_ref && vrfl == cm->comp_var_ref[0]) ||
+                (vrfl == cm->comp_fixed_ref && vrfa == cm->comp_var_ref[0])) {
+              pred_context = 4;
+            } else if (vrfa == vrfl) {
+              pred_context = 3;
+            } else {
+              pred_context = 1;
+            }
+          } else if (l_sg || a_sg) {  // single/comp
+            MV_REFERENCE_FRAME vrfc = l_sg ? vrfa : vrfl;
+            MV_REFERENCE_FRAME rfs = a_sg ? vrfa : vrfl;
+
+            if (vrfc == cm->comp_var_ref[1] && rfs != cm->comp_var_ref[1]) {
+              pred_context = 1;
+            } else if (rfs == cm->comp_var_ref[1] &&
+                       vrfc != cm->comp_var_ref[1]) {
+              pred_context = 2;
+            } else {
+              pred_context = 4;
+            }
+          } else if (vrfa == vrfl) {  // comp/comp
+            pred_context = 4;
+          } else {
+            pred_context = 2;
+          }
+        }
+      } else if (above_in_image || left_in_image) {  // one edge available
+        const MODE_INFO *edge = above_in_image ? above_mi : left_mi;
+
+        if (edge->mbmi.ref_frame[0] == INTRA_FRAME) {
+          pred_context = 2;
+        } else if (edge->mbmi.ref_frame[1] > INTRA_FRAME) {
+          pred_context =
+              4 * edge->mbmi.ref_frame[var_ref_idx] != cm->comp_var_ref[1];
+        } else {
+          pred_context = 3 * edge->mbmi.ref_frame[0] != cm->comp_var_ref[1];
+        }
+      } else {  // no edges available (2)
+        pred_context = 2;
+      }
+      assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
+      break;
+    }
+
+    case PRED_SINGLE_REF_P1: {
+      if (above_in_image && left_in_image) {  // both edges available
+        if (above_mi->mbmi.ref_frame[0] == INTRA_FRAME &&
+            left_mi->mbmi.ref_frame[0] == INTRA_FRAME) {
+          pred_context = 2;
+        } else if (above_mi->mbmi.ref_frame[0] == INTRA_FRAME ||
+                   left_mi->mbmi.ref_frame[0] == INTRA_FRAME) {
+          const MODE_INFO *edge = above_mi->mbmi.ref_frame[0] == INTRA_FRAME ?
+                                  left_mi : above_mi;
+
+          if (edge->mbmi.ref_frame[1] <= INTRA_FRAME) {
+            pred_context = 4 * (edge->mbmi.ref_frame[0] == LAST_FRAME);
+          } else {
+            pred_context = 1 + (edge->mbmi.ref_frame[0] == LAST_FRAME ||
+                                edge->mbmi.ref_frame[1] == LAST_FRAME);
+          }
+        } else if (above_mi->mbmi.ref_frame[1] <= INTRA_FRAME &&
+                   left_mi->mbmi.ref_frame[1] <= INTRA_FRAME) {
+          pred_context = 2 * (above_mi->mbmi.ref_frame[0] == LAST_FRAME) +
+                         2 * (left_mi->mbmi.ref_frame[0] == LAST_FRAME);
+        } else if (above_mi->mbmi.ref_frame[1] > INTRA_FRAME &&
+                   left_mi->mbmi.ref_frame[1] > INTRA_FRAME) {
+          pred_context = 1 + (above_mi->mbmi.ref_frame[0] == LAST_FRAME ||
+                              above_mi->mbmi.ref_frame[1] == LAST_FRAME ||
+                              left_mi->mbmi.ref_frame[0] == LAST_FRAME ||
+                              left_mi->mbmi.ref_frame[1] == LAST_FRAME);
+        } else {
+          MV_REFERENCE_FRAME rfs = above_mi->mbmi.ref_frame[1] <= INTRA_FRAME ?
+              above_mi->mbmi.ref_frame[0] : left_mi->mbmi.ref_frame[0];
+          MV_REFERENCE_FRAME crf1 = above_mi->mbmi.ref_frame[1] > INTRA_FRAME ?
+              above_mi->mbmi.ref_frame[0] : left_mi->mbmi.ref_frame[0];
+          MV_REFERENCE_FRAME crf2 = above_mi->mbmi.ref_frame[1] > INTRA_FRAME ?
+              above_mi->mbmi.ref_frame[1] : left_mi->mbmi.ref_frame[1];
+
+          if (rfs == LAST_FRAME) {
+            pred_context = 3 + (crf1 == LAST_FRAME || crf2 == LAST_FRAME);
+          } else {
+            pred_context = crf1 == LAST_FRAME || crf2 == LAST_FRAME;
+          }
+        }
+      } else if (above_in_image || left_in_image) {  // one edge available
+        const MODE_INFO *edge = above_in_image ? above_mi : left_mi;
+
+        if (edge->mbmi.ref_frame[0] == INTRA_FRAME) {
+          pred_context = 2;
+        } else if (edge->mbmi.ref_frame[1] <= INTRA_FRAME) {
+          pred_context = 4 * (edge->mbmi.ref_frame[0] == LAST_FRAME);
+        } else {
+          pred_context = 1 + (edge->mbmi.ref_frame[0] == LAST_FRAME ||
+                              edge->mbmi.ref_frame[1] == LAST_FRAME);
+        }
+      } else {  // no edges available (2)
+        pred_context = 2;
+      }
+      assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
+      break;
+    }
+
+    case PRED_SINGLE_REF_P2: {
+      if (above_in_image && left_in_image) {  // both edges available
+        if (above_mi->mbmi.ref_frame[0] == INTRA_FRAME &&
+            left_mi->mbmi.ref_frame[0] == INTRA_FRAME) {
+          pred_context = 2;
+        } else if (above_mi->mbmi.ref_frame[0] == INTRA_FRAME ||
+                   left_mi->mbmi.ref_frame[0] == INTRA_FRAME) {
+          const MODE_INFO *edge = above_mi->mbmi.ref_frame[0] == INTRA_FRAME ?
+                                  left_mi : above_mi;
+
+          if (edge->mbmi.ref_frame[1] <= INTRA_FRAME) {
+            if (edge->mbmi.ref_frame[0] == LAST_FRAME) {
+              pred_context = 3;
+            } else {
+              pred_context = 4 * (edge->mbmi.ref_frame[0] == GOLDEN_FRAME);
+            }
+          } else {
+            pred_context = 1 + 2 * (edge->mbmi.ref_frame[0] == GOLDEN_FRAME ||
+                                    edge->mbmi.ref_frame[1] == GOLDEN_FRAME);
+          }
+        } else if (above_mi->mbmi.ref_frame[1] <= INTRA_FRAME &&
+                   left_mi->mbmi.ref_frame[1] <= INTRA_FRAME) {
+          if (above_mi->mbmi.ref_frame[0] == LAST_FRAME &&
+              left_mi->mbmi.ref_frame[0] == LAST_FRAME) {
+            pred_context = 3;
+          } else if (above_mi->mbmi.ref_frame[0] == LAST_FRAME ||
+                     left_mi->mbmi.ref_frame[0] == LAST_FRAME) {
+            const MODE_INFO *edge = above_mi->mbmi.ref_frame[0] == LAST_FRAME ?
+                                    left_mi : above_mi;
+
+            pred_context = 4 * (edge->mbmi.ref_frame[0] == GOLDEN_FRAME);
+          } else {
+            pred_context = 2 * (above_mi->mbmi.ref_frame[0] == GOLDEN_FRAME) +
+                           2 * (left_mi->mbmi.ref_frame[0] == GOLDEN_FRAME);
+          }
+        } else if (above_mi->mbmi.ref_frame[1] > INTRA_FRAME &&
+                   left_mi->mbmi.ref_frame[1] > INTRA_FRAME) {
+          if (above_mi->mbmi.ref_frame[0] == left_mi->mbmi.ref_frame[0] &&
+              above_mi->mbmi.ref_frame[1] == left_mi->mbmi.ref_frame[1]) {
+            pred_context = 3 * (above_mi->mbmi.ref_frame[0] == GOLDEN_FRAME ||
+                                above_mi->mbmi.ref_frame[1] == GOLDEN_FRAME ||
+                                left_mi->mbmi.ref_frame[0] == GOLDEN_FRAME ||
+                                left_mi->mbmi.ref_frame[1] == GOLDEN_FRAME);
+          } else {
+            pred_context = 2;
+          }
+        } else {
+          MV_REFERENCE_FRAME rfs = above_mi->mbmi.ref_frame[1] <= INTRA_FRAME ?
+              above_mi->mbmi.ref_frame[0] : left_mi->mbmi.ref_frame[0];
+          MV_REFERENCE_FRAME crf1 = above_mi->mbmi.ref_frame[1] > INTRA_FRAME ?
+              above_mi->mbmi.ref_frame[0] : left_mi->mbmi.ref_frame[0];
+          MV_REFERENCE_FRAME crf2 = above_mi->mbmi.ref_frame[1] > INTRA_FRAME ?
+              above_mi->mbmi.ref_frame[1] : left_mi->mbmi.ref_frame[1];
+
+          if (rfs == GOLDEN_FRAME) {
+            pred_context = 3 + (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME);
+          } else if (rfs == ALTREF_FRAME) {
+            pred_context = crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME;
+          } else {
+            pred_context =
+                1 + 2 * (crf1 == GOLDEN_FRAME || crf2 == GOLDEN_FRAME);
+          }
+        }
+      } else if (above_in_image || left_in_image) {  // one edge available
+        const MODE_INFO *edge = above_in_image ? above_mi : left_mi;
+
+        if (edge->mbmi.ref_frame[0] == INTRA_FRAME ||
+            (edge->mbmi.ref_frame[0] == LAST_FRAME &&
+             edge->mbmi.ref_frame[1] <= INTRA_FRAME)) {
+          pred_context = 2;
+        } else if (edge->mbmi.ref_frame[1] <= INTRA_FRAME) {
+          pred_context = 4 * (edge->mbmi.ref_frame[0] == GOLDEN_FRAME);
+        } else {
+          pred_context = 3 * (edge->mbmi.ref_frame[0] == GOLDEN_FRAME ||
+                              edge->mbmi.ref_frame[1] == GOLDEN_FRAME);
+        }
+      } else {  // no edges available (2)
+        pred_context = 2;
+      }
+      assert(pred_context >= 0 && pred_context < REF_CONTEXTS);
+      break;
+    }
+
     default:
+      assert(0);
       pred_context = 0;  // *** add error trap code.
       break;
   }
@@ -106,16 +367,20 @@
   switch (pred_id) {
     case PRED_SEG_ID:
       return cm->segment_pred_probs[pred_context];
-    case PRED_REF:
-      return cm->ref_pred_probs[pred_context];
-    case PRED_COMP:
-      // In keeping with convention elsewhre the probability returned is
-      // the probability of a "0" outcome which in this case means the
-      // probability of comp pred off.
-      return cm->prob_comppred[pred_context];
     case PRED_MBSKIP:
       return cm->mbskip_pred_probs[pred_context];
+    case PRED_INTRA_INTER:
+      return cm->fc.intra_inter_prob[pred_context];
+    case PRED_COMP_INTER_INTER:
+      return cm->fc.comp_inter_prob[pred_context];
+    case PRED_COMP_REF_P:
+      return cm->fc.comp_ref_prob[pred_context];
+    case PRED_SINGLE_REF_P1:
+      return cm->fc.single_ref_prob[pred_context][0];
+    case PRED_SINGLE_REF_P2:
+      return cm->fc.single_ref_prob[pred_context][1];
     default:
+      assert(0);
       return 128;  // *** add error trap code.
   }
 }
@@ -128,20 +393,10 @@
   const int pred_context = vp9_get_pred_context(cm, xd, pred_id);
 
   switch (pred_id) {
-    case PRED_SEG_ID:
-      return &cm->segment_pred_probs[pred_context];
-    case PRED_REF:
-      return &cm->ref_pred_probs[pred_context];
-    case PRED_COMP:
-      // In keeping with convention elsewhre the probability returned is
-      // the probability of a "0" outcome which in this case means the
-      // probability of comp pred off.
-      return &cm->prob_comppred[pred_context];
-    case PRED_MBSKIP:
-      return &cm->mbskip_pred_probs[pred_context];
     case PRED_SWITCHABLE_INTERP:
       return &cm->fc.switchable_interp_prob[pred_context][0];
     default:
+      assert(0);
       return NULL;  // *** add error trap code.
   }
 }
@@ -153,11 +408,10 @@
   switch (pred_id) {
     case PRED_SEG_ID:
       return xd->mode_info_context->mbmi.seg_id_predicted;
-    case PRED_REF:
-      return  xd->mode_info_context->mbmi.ref_predicted;
     case PRED_MBSKIP:
       return xd->mode_info_context->mbmi.mb_skip_coeff;
     default:
+      assert(0);
       return 0;  // *** add error trap code.
   }
 }
@@ -186,14 +440,6 @@
       }
       break;
 
-    case PRED_REF:
-      for (y = 0; y < y_mis; y++) {
-        for (x = 0; x < x_mis; x++) {
-          xd->mode_info_context[y * mis + x].mbmi.ref_predicted = pred_flag;
-        }
-      }
-      break;
-
     case PRED_MBSKIP:
       for (y = 0; y < y_mis; y++) {
         for (x = 0; x < x_mis; x++) {
@@ -203,6 +449,7 @@
       break;
 
     default:
+      assert(0);
       // *** add error trap code.
       break;
   }
@@ -231,138 +478,3 @@
   }
   return segment_id;
 }
-
-MV_REFERENCE_FRAME vp9_get_pred_ref(const VP9_COMMON *const cm,
-                                    const MACROBLOCKD *const xd) {
-  MODE_INFO *m = xd->mode_info_context;
-
-  MV_REFERENCE_FRAME left;
-  MV_REFERENCE_FRAME above;
-  MV_REFERENCE_FRAME above_left;
-  MV_REFERENCE_FRAME pred_ref = LAST_FRAME;
-
-  int segment_id = xd->mode_info_context->mbmi.segment_id;
-  int i;
-
-  unsigned char frame_allowed[MAX_REF_FRAMES] = {1, 1, 1, 1};
-  unsigned char ref_score[MAX_REF_FRAMES];
-  unsigned char best_score = 0;
-  unsigned char left_in_image;
-  unsigned char above_in_image;
-  unsigned char above_left_in_image;
-
-  // Is segment coding ennabled
-  int seg_ref_active = vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME);
-
-  // Special case treatment if segment coding is enabled.
-  // Dont allow prediction of a reference frame that the segment
-  // does not allow
-  if (seg_ref_active) {
-    for (i = 0; i < MAX_REF_FRAMES; i++) {
-      frame_allowed[i] =
-        vp9_check_segref(xd, segment_id, i);
-
-      // Score set to 0 if ref frame not allowed
-      ref_score[i] = cm->ref_scores[i] * frame_allowed[i];
-    }
-  } else
-    vpx_memcpy(ref_score, cm->ref_scores, sizeof(ref_score));
-
-  // Reference frames used by neighbours
-  left = (m - 1)->mbmi.ref_frame;
-  above = (m - cm->mode_info_stride)->mbmi.ref_frame;
-  above_left = (m - 1 - cm->mode_info_stride)->mbmi.ref_frame;
-
-  // Are neighbours in image
-  left_in_image = (m - 1)->mbmi.mb_in_image && xd->left_available;
-  above_in_image = (m - cm->mode_info_stride)->mbmi.mb_in_image;
-  above_left_in_image = (m - 1 - cm->mode_info_stride)->mbmi.mb_in_image &&
-                        xd->left_available;
-
-  // Adjust scores for candidate reference frames based on neigbours
-  if (frame_allowed[left] && left_in_image) {
-    ref_score[left] += 16;
-    if (above_left_in_image && (left == above_left))
-      ref_score[left] += 4;
-  }
-  if (frame_allowed[above] && above_in_image) {
-    ref_score[above] += 16;
-    if (above_left_in_image && (above == above_left))
-      ref_score[above] += 4;
-  }
-
-  // Now choose the candidate with the highest score
-  for (i = 0; i < MAX_REF_FRAMES; i++) {
-    if (ref_score[i] > best_score) {
-      pred_ref = i;
-      best_score = ref_score[i];
-    }
-  }
-
-  return pred_ref;
-}
-
-// Functions to computes a set of modified reference frame probabilities
-// to use when the prediction of the reference frame value fails
-void vp9_calc_ref_probs(int *count, vp9_prob *probs) {
-  int tot_count = count[0] + count[1] + count[2] + count[3];
-  probs[0] = get_prob(count[0], tot_count);
-
-  tot_count -= count[0];
-  probs[1] = get_prob(count[1], tot_count);
-
-  tot_count -= count[1];
-  probs[2] = get_prob(count[2], tot_count);
-}
-
-// Computes a set of modified conditional probabilities for the reference frame
-// Values willbe set to 0 for reference frame options that are not possible
-// because wither they were predicted and prediction has failed or because
-// they are not allowed for a given segment.
-void vp9_compute_mod_refprobs(VP9_COMMON *const cm) {
-  int norm_cnt[MAX_REF_FRAMES];
-  const int intra_count = cm->prob_intra_coded;
-  const int inter_count = (255 - intra_count);
-  const int last_count = (inter_count * cm->prob_last_coded) / 255;
-  const int gfarf_count = inter_count - last_count;
-  const int gf_count = (gfarf_count * cm->prob_gf_coded) / 255;
-  const int arf_count = gfarf_count - gf_count;
-
-  // Work out modified reference frame probabilities to use where prediction
-  // of the reference frame fails
-  norm_cnt[0] = 0;
-  norm_cnt[1] = last_count;
-  norm_cnt[2] = gf_count;
-  norm_cnt[3] = arf_count;
-  vp9_calc_ref_probs(norm_cnt, cm->mod_refprobs[INTRA_FRAME]);
-  cm->mod_refprobs[INTRA_FRAME][0] = 0;    // This branch implicit
-
-  norm_cnt[0] = intra_count;
-  norm_cnt[1] = 0;
-  norm_cnt[2] = gf_count;
-  norm_cnt[3] = arf_count;
-  vp9_calc_ref_probs(norm_cnt, cm->mod_refprobs[LAST_FRAME]);
-  cm->mod_refprobs[LAST_FRAME][1] = 0;    // This branch implicit
-
-  norm_cnt[0] = intra_count;
-  norm_cnt[1] = last_count;
-  norm_cnt[2] = 0;
-  norm_cnt[3] = arf_count;
-  vp9_calc_ref_probs(norm_cnt, cm->mod_refprobs[GOLDEN_FRAME]);
-  cm->mod_refprobs[GOLDEN_FRAME][2] = 0;  // This branch implicit
-
-  norm_cnt[0] = intra_count;
-  norm_cnt[1] = last_count;
-  norm_cnt[2] = gf_count;
-  norm_cnt[3] = 0;
-  vp9_calc_ref_probs(norm_cnt, cm->mod_refprobs[ALTREF_FRAME]);
-  cm->mod_refprobs[ALTREF_FRAME][2] = 0;  // This branch implicit
-
-  // Score the reference frames based on overal frequency.
-  // These scores contribute to the prediction choices.
-  // Max score 17 min 1
-  cm->ref_scores[INTRA_FRAME] = 1 + (intra_count * 16 / 255);
-  cm->ref_scores[LAST_FRAME] = 1 + (last_count * 16 / 255);
-  cm->ref_scores[GOLDEN_FRAME] = 1 + (gf_count * 16 / 255);
-  cm->ref_scores[ALTREF_FRAME] = 1 + (arf_count * 16 / 255);
-}
diff --git a/vp9/common/vp9_pred_common.h b/vp9/common/vp9_pred_common.h
index afb0bfe..6d52997 100644
--- a/vp9/common/vp9_pred_common.h
+++ b/vp9/common/vp9_pred_common.h
@@ -17,10 +17,13 @@
 // Predicted items
 typedef enum {
   PRED_SEG_ID = 0,  // Segment identifier
-  PRED_REF = 1,
-  PRED_COMP = 2,
-  PRED_MBSKIP = 3,
-  PRED_SWITCHABLE_INTERP = 4
+  PRED_MBSKIP = 1,
+  PRED_SWITCHABLE_INTERP = 2,
+  PRED_INTRA_INTER = 3,
+  PRED_COMP_INTER_INTER = 4,
+  PRED_SINGLE_REF_P1 = 5,
+  PRED_SINGLE_REF_P2 = 6,
+  PRED_COMP_REF_P = 7,
 } PRED_ID;
 
 unsigned char vp9_get_pred_context(const VP9_COMMON *const cm,
@@ -46,9 +49,4 @@
 int vp9_get_pred_mi_segid(VP9_COMMON *cm, BLOCK_SIZE_TYPE sb_type,
                           int mi_row, int mi_col);
 
-MV_REFERENCE_FRAME vp9_get_pred_ref(const VP9_COMMON *const cm,
-                                    const MACROBLOCKD *const xd);
-
-void vp9_compute_mod_refprobs(VP9_COMMON *const cm);
-
 #endif  // VP9_COMMON_VP9_PRED_COMMON_H_
diff --git a/vp9/common/vp9_reconinter.c b/vp9/common/vp9_reconinter.c
index 679cc7d..93faa8c 100644
--- a/vp9/common/vp9_reconinter.c
+++ b/vp9/common/vp9_reconinter.c
@@ -171,8 +171,8 @@
     MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi;
 
     set_scale_factors(xd,
-                      mbmi->ref_frame - 1,
-                      mbmi->second_ref_frame - 1,
+                      mbmi->ref_frame[0] - 1,
+                      mbmi->ref_frame[1] - 1,
                       cm->active_ref_scale);
   }
 
@@ -386,7 +386,7 @@
   const int bhl = b_height_log2(bsize) - xd->plane[plane].subsampling_y;
   const int bh = 4 << bhl, bw = 4 << bwl;
   const int x = 4 * (block & ((1 << bwl) - 1)), y = 4 * (block >> bwl);
-  const int use_second_ref = xd->mode_info_context->mbmi.second_ref_frame > 0;
+  const int use_second_ref = xd->mode_info_context->mbmi.ref_frame[1] > 0;
   int which_mv;
 
   assert(x < bw);
diff --git a/vp9/common/vp9_reconintra.c b/vp9/common/vp9_reconintra.c
index 4a4634b..85dfe51 100644
--- a/vp9/common/vp9_reconintra.c
+++ b/vp9/common/vp9_reconintra.c
@@ -204,6 +204,8 @@
   // 129  G   H  ..  S   T   T   T   T   T
   // ..
 
+  assert(bw == bh);
+
   if (left_available) {
     for (i = 0; i < bh; i++)
       yleft_col[i] = src[i * src_stride - 1];
@@ -271,89 +273,22 @@
       }
       break;
     case D45_PRED:
+      d45_predictor(ypred_ptr, y_stride, bw, bh, yabove_row, yleft_col);
+      break;
     case D135_PRED:
+      d135_predictor(ypred_ptr, y_stride, bw, bh, yabove_row, yleft_col);
+      break;
     case D117_PRED:
+      d117_predictor(ypred_ptr, y_stride, bw, bh, yabove_row, yleft_col);
+      break;
     case D153_PRED:
+      d153_predictor(ypred_ptr, y_stride, bw, bh, yabove_row, yleft_col);
+      break;
     case D27_PRED:
+      d27_predictor(ypred_ptr, y_stride, bw, bh, yabove_row, yleft_col);
+      break;
     case D63_PRED:
-      if (bw == bh) {
-        switch (mode) {
-          case D45_PRED:
-            d45_predictor(ypred_ptr, y_stride, bw, bh,  yabove_row, yleft_col);
-            break;
-          case D135_PRED:
-            d135_predictor(ypred_ptr, y_stride, bw, bh,  yabove_row, yleft_col);
-            break;
-          case D117_PRED:
-            d117_predictor(ypred_ptr, y_stride, bw, bh,  yabove_row, yleft_col);
-            break;
-          case D153_PRED:
-            d153_predictor(ypred_ptr, y_stride, bw, bh,  yabove_row, yleft_col);
-            break;
-          case D27_PRED:
-            d27_predictor(ypred_ptr, y_stride, bw, bh,  yabove_row, yleft_col);
-            break;
-          case D63_PRED:
-            d63_predictor(ypred_ptr, y_stride, bw, bh,  yabove_row, yleft_col);
-            break;
-          default:
-            assert(0);
-        }
-      } else if (bw > bh) {
-        uint8_t pred[64*64];
-        vpx_memset(yleft_col + bh, yleft_col[bh - 1], bw - bh);
-        switch (mode) {
-          case D45_PRED:
-            d45_predictor(pred, 64, bw, bw,  yabove_row, yleft_col);
-            break;
-          case D135_PRED:
-            d135_predictor(pred, 64, bw, bw,  yabove_row, yleft_col);
-            break;
-          case D117_PRED:
-            d117_predictor(pred, 64, bw, bw,  yabove_row, yleft_col);
-            break;
-          case D153_PRED:
-            d153_predictor(pred, 64, bw, bw,  yabove_row, yleft_col);
-            break;
-          case D27_PRED:
-            d27_predictor(pred, 64, bw, bw,  yabove_row, yleft_col);
-            break;
-          case D63_PRED:
-            d63_predictor(pred, 64, bw, bw,  yabove_row, yleft_col);
-            break;
-          default:
-            assert(0);
-        }
-        for (i = 0; i < bh; i++)
-          vpx_memcpy(ypred_ptr + y_stride * i, pred + i * 64, bw);
-      } else {
-        uint8_t pred[64 * 64];
-        vpx_memset(yabove_row + bw * 2, yabove_row[bw * 2 - 1], (bh - bw) * 2);
-        switch (mode) {
-          case D45_PRED:
-            d45_predictor(pred, 64, bh, bh,  yabove_row, yleft_col);
-            break;
-          case D135_PRED:
-            d135_predictor(pred, 64, bh, bh,  yabove_row, yleft_col);
-            break;
-          case D117_PRED:
-            d117_predictor(pred, 64, bh, bh,  yabove_row, yleft_col);
-            break;
-          case D153_PRED:
-            d153_predictor(pred, 64, bh, bh,  yabove_row, yleft_col);
-            break;
-          case D27_PRED:
-            d27_predictor(pred, 64, bh, bh,  yabove_row, yleft_col);
-            break;
-          case D63_PRED:
-            d63_predictor(pred, 64, bh, bh,  yabove_row, yleft_col);
-            break;
-          default:
-            assert(0);
-        }
-        for (i = 0; i < bh; i++)
-          vpx_memcpy(ypred_ptr + y_stride * i, pred + i * 64, bw);
-      }
+      d63_predictor(ypred_ptr, y_stride, bw, bh, yabove_row, yleft_col);
       break;
     default:
       break;
diff --git a/vp9/common/vp9_rtcd_defs.sh b/vp9/common/vp9_rtcd_defs.sh
index 7b834d7..0517e92 100644
--- a/vp9/common/vp9_rtcd_defs.sh
+++ b/vp9/common/vp9_rtcd_defs.sh
@@ -86,6 +86,25 @@
 #
 # Loopfilter
 #
+if [ "$CONFIG_NEW_LOOPFILTER" = "yes" ]; then
+prototype void vp9_mb_lpf_vertical_edge_w "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count"
+specialize vp9_mb_lpf_vertical_edge_w
+
+prototype void vp9_mbloop_filter_vertical_edge "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count"
+specialize vp9_mbloop_filter_vertical_edge
+
+prototype void vp9_loop_filter_vertical_edge "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count"
+specialize vp9_loop_filter_vertical_edge
+
+prototype void vp9_mb_lpf_horizontal_edge_w "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count"
+specialize vp9_mb_lpf_horizontal_edge_w
+
+prototype void vp9_mbloop_filter_horizontal_edge "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count"
+specialize vp9_mbloop_filter_horizontal_edge
+
+prototype void vp9_loop_filter_horizontal_edge "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count"
+specialize vp9_loop_filter_horizontal_edge
+else
 prototype void vp9_loop_filter_mbv "uint8_t *y, uint8_t *u, uint8_t *v, int ystride, int uv_stride, struct loop_filter_info *lfi"
 specialize vp9_loop_filter_mbv sse2
 
@@ -109,6 +128,7 @@
 
 prototype void vp9_lpf_mbv_w "unsigned char *y_ptr, unsigned char *u_ptr, unsigned char *v_ptr, int y_stride, int uv_stride, struct loop_filter_info *lfi"
 specialize vp9_lpf_mbv_w sse2
+fi
 
 #
 # post proc
diff --git a/vp9/common/vp9_seg_common.c b/vp9/common/vp9_seg_common.c
index 67dfeae..890dcce 100644
--- a/vp9/common/vp9_seg_common.c
+++ b/vp9/common/vp9_seg_common.c
@@ -13,7 +13,7 @@
 #include "vp9/common/vp9_seg_common.h"
 
 static const int seg_feature_data_signed[SEG_LVL_MAX] = { 1, 1, 0, 0 };
-static const int seg_feature_data_max[SEG_LVL_MAX] = { MAXQ, 63, 15, 15 };
+static const int seg_feature_data_max[SEG_LVL_MAX] = { MAXQ, 63, 15, 0 };
 
 // These functions provide access to new segment level features.
 // Eventually these function may be "optimized out" but for the moment,
diff --git a/vp9/decoder/vp9_dboolhuff.c b/vp9/decoder/vp9_dboolhuff.c
index 9921ea7..df77d65 100644
--- a/vp9/decoder/vp9_dboolhuff.c
+++ b/vp9/decoder/vp9_dboolhuff.c
@@ -14,6 +14,8 @@
 #include "vp9/decoder/vp9_dboolhuff.h"
 
 int vp9_reader_init(vp9_reader *r, const uint8_t *buffer, size_t size) {
+  int marker_bit;
+
   r->buffer_end = buffer + size;
   r->buffer = buffer;
   r->value = 0;
@@ -24,7 +26,8 @@
     return 1;
 
   vp9_reader_fill(r);
-  return 0;
+  marker_bit = vp9_read_bit(r);
+  return marker_bit != 0;
 }
 
 void vp9_reader_fill(vp9_reader *r) {
diff --git a/vp9/decoder/vp9_decodemv.c b/vp9/decoder/vp9_decodemv.c
index efd852b..cb16ccd 100644
--- a/vp9/decoder/vp9_decodemv.c
+++ b/vp9/decoder/vp9_decodemv.c
@@ -20,6 +20,7 @@
 #include "vp9/common/vp9_pred_common.h"
 #include "vp9/common/vp9_entropy.h"
 #include "vp9/decoder/vp9_decodemv.h"
+#include "vp9/decoder/vp9_decodframe.h"
 #include "vp9/common/vp9_mvref_common.h"
 #if CONFIG_DEBUG
 #include <assert.h>
@@ -63,12 +64,20 @@
 }
 
 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
+                                BLOCK_SIZE_TYPE bsize) {
+  int tx_probs_offset = get_tx_probs_offset(bsize);
+  TX_SIZE txfm_size = vp9_read(r, cm->fc.tx_probs[tx_probs_offset]);
+  if (txfm_size != TX_4X4 && bsize >= BLOCK_SIZE_MB16X16) {
+    txfm_size += vp9_read(r, cm->fc.tx_probs[tx_probs_offset + 1]);
+    if (txfm_size != TX_8X8 && bsize >= BLOCK_SIZE_SB32X32)
+      txfm_size += vp9_read(r, cm->fc.tx_probs[tx_probs_offset + 2]);
+  }
+  if (bsize >= BLOCK_SIZE_SB32X32) {
+    cm->fc.tx_count_32x32p[txfm_size]++;
+  } else if (bsize >= BLOCK_SIZE_MB16X16) {
+    cm->fc.tx_count_16x16p[txfm_size]++;
+  } else {
+    cm->fc.tx_count_8x8p[txfm_size]++;
   }
   return txfm_size;
 }
@@ -80,7 +89,6 @@
   VP9_COMMON *const cm = &pbi->common;
   MACROBLOCKD *const xd = &pbi->mb;
   const int mis = cm->mode_info_stride;
-  m->mbmi.ref_frame = INTRA_FRAME;
 
   // Read segmentation map if it is being updated explicitly this frame
   m->mbmi.segment_id = 0;
@@ -96,9 +104,7 @@
 
   if (cm->txfm_mode == TX_MODE_SELECT &&
       m->mbmi.sb_type >= BLOCK_SIZE_SB8X8) {
-    const int allow_16x16 = m->mbmi.sb_type >= BLOCK_SIZE_MB16X16;
-    const int allow_32x32 = m->mbmi.sb_type >= BLOCK_SIZE_SB32X32;
-    m->mbmi.txfm_size = select_txfm_size(cm, r, allow_16x16, allow_32x32);
+    m->mbmi.txfm_size = select_txfm_size(cm, r,  m->mbmi.sb_type);
   } else if (cm->txfm_mode >= ALLOW_32X32 &&
              m->mbmi.sb_type >= BLOCK_SIZE_SB32X32) {
     m->mbmi.txfm_size = TX_32X32;
@@ -113,7 +119,7 @@
   }
 
   // luma mode
-  m->mbmi.ref_frame = INTRA_FRAME;
+  m->mbmi.ref_frame[0] = INTRA_FRAME;
   if (m->mbmi.sb_type >= BLOCK_SIZE_SB8X8) {
     const MB_PREDICTION_MODE A = above_block_mode(m, 0, mis);
     const MB_PREDICTION_MODE L = xd->left_available ?
@@ -231,17 +237,13 @@
 }
 
 // Read the referncence frame
-static MV_REFERENCE_FRAME read_ref_frame(VP9D_COMP *pbi,
-                                         vp9_reader *r,
-                                         int segment_id) {
-  MV_REFERENCE_FRAME ref_frame;
+static void read_ref_frame(VP9D_COMP *pbi, vp9_reader *r,
+                           int segment_id, MV_REFERENCE_FRAME ref_frame[2]) {
   VP9_COMMON *const cm = &pbi->common;
   MACROBLOCKD *const xd = &pbi->mb;
-
   int seg_ref_count = 0;
   const int seg_ref_active = vp9_segfeature_active(xd, segment_id,
                                                    SEG_LVL_REF_FRAME);
-
   const int intra = vp9_check_segref(xd, segment_id, INTRA_FRAME);
   const int last = vp9_check_segref(xd, segment_id, LAST_FRAME);
   const int golden = vp9_check_segref(xd, segment_id, GOLDEN_FRAME);
@@ -255,79 +257,43 @@
   // Segment reference frame features not available or allows for
   // multiple reference frame options
   if (!seg_ref_active || seg_ref_count > 1) {
-    // Values used in prediction model coding
-    MV_REFERENCE_FRAME pred_ref;
+    int is_comp;
+    int comp_ctx = vp9_get_pred_context(cm, xd, PRED_COMP_INTER_INTER);
 
-    // Get the context probability the prediction flag
-    vp9_prob pred_prob = vp9_get_pred_prob(cm, xd, PRED_REF);
-
-    // Read the prediction status flag
-    unsigned char prediction_flag = vp9_read(r, pred_prob);
-
-    // Store the prediction flag.
-    vp9_set_pred_flag(xd, PRED_REF, prediction_flag);
-
-    // Get the predicted reference frame.
-    pred_ref = vp9_get_pred_ref(cm, xd);
-
-    // If correctly predicted then use the predicted value
-    if (prediction_flag) {
-      ref_frame = pred_ref;
+    if (cm->comp_pred_mode == HYBRID_PREDICTION) {
+      is_comp = vp9_read(r, cm->fc.comp_inter_prob[comp_ctx]);
+      cm->fc.comp_inter_count[comp_ctx][is_comp]++;
     } else {
-      // decode the explicitly coded value
-      vp9_prob mod_refprobs[PREDICTION_PROBS];
-      vpx_memcpy(mod_refprobs, cm->mod_refprobs[pred_ref],
-                 sizeof(mod_refprobs));
+      is_comp = cm->comp_pred_mode == COMP_PREDICTION_ONLY;
+    }
 
-      // If segment coding enabled blank out options that cant occur by
-      // setting the branch probability to 0.
-      if (seg_ref_active) {
-        mod_refprobs[INTRA_FRAME] *= intra;
-        mod_refprobs[LAST_FRAME] *= last;
-        mod_refprobs[GOLDEN_FRAME] *= golden * altref;
-      }
+    // FIXME(rbultje) I'm pretty sure this breaks segmentation ref frame coding
+    if (is_comp) {
+      int b, fix_ref_idx = cm->ref_frame_sign_bias[cm->comp_fixed_ref];
+      int ref_ctx = vp9_get_pred_context(cm, xd, PRED_COMP_REF_P);
 
-      // Default to INTRA_FRAME (value 0)
-      ref_frame = INTRA_FRAME;
-
-      // Do we need to decode the Intra/Inter branch
-      if (mod_refprobs[0])
-        ref_frame = vp9_read(r, mod_refprobs[0]);
-      else
-        ref_frame++;
-
-      if (ref_frame) {
-        // Do we need to decode the Last/Gf_Arf branch
-        if (mod_refprobs[1])
-          ref_frame += vp9_read(r, mod_refprobs[1]);
-        else
-          ref_frame++;
-
-        if (ref_frame > 1) {
-          // Do we need to decode the GF/Arf branch
-          if (mod_refprobs[2]) {
-            ref_frame += vp9_read(r, mod_refprobs[2]);
-          } else {
-            if (seg_ref_active)
-              ref_frame = pred_ref == GOLDEN_FRAME || !golden ? ALTREF_FRAME
-                                                              : GOLDEN_FRAME;
-            else
-              ref_frame = pred_ref == GOLDEN_FRAME ? ALTREF_FRAME
-                                                   : GOLDEN_FRAME;
-          }
-        }
+      ref_frame[fix_ref_idx]  = cm->comp_fixed_ref;
+      b = vp9_read(r, cm->fc.comp_ref_prob[ref_ctx]);
+      cm->fc.comp_ref_count[ref_ctx][b]++;
+      ref_frame[!fix_ref_idx] = cm->comp_var_ref[b];
+    } else {
+      int ref1_ctx = vp9_get_pred_context(cm, xd, PRED_SINGLE_REF_P1);
+      ref_frame[1] = NONE;
+      if (vp9_read(r, cm->fc.single_ref_prob[ref1_ctx][0])) {
+        int ref2_ctx = vp9_get_pred_context(cm, xd, PRED_SINGLE_REF_P2);
+        int b2 = vp9_read(r, cm->fc.single_ref_prob[ref2_ctx][1]);
+        ref_frame[0] = b2 ? ALTREF_FRAME : GOLDEN_FRAME;
+        cm->fc.single_ref_count[ref1_ctx][0][1]++;
+        cm->fc.single_ref_count[ref2_ctx][1][b2]++;
+      } else {
+        ref_frame[0] = LAST_FRAME;
+        cm->fc.single_ref_count[ref1_ctx][0][0]++;
       }
     }
   } else {
-    // Segment reference frame features are enabled
-    // The reference frame for the mb is considered as correclty predicted
-    // if it is signaled at the segment level for the purposes of the
-    // common prediction model
-    vp9_set_pred_flag(xd, PRED_REF, 1);
-    ref_frame = vp9_get_pred_ref(cm, xd);
+    ref_frame[0] = last ? LAST_FRAME : golden ? GOLDEN_FRAME : ALTREF_FRAME;
+    ref_frame[1] = NONE;
   }
-
-  return ref_frame;
 }
 
 static MB_PREDICTION_MODE read_sb_mv_ref(vp9_reader *r, const vp9_prob *p) {
@@ -344,12 +310,28 @@
 };
 #endif
 
-static void read_switchable_interp_probs(VP9D_COMP* const pbi, vp9_reader *r) {
-  VP9_COMMON *const cm = &pbi->common;
+static void read_switchable_interp_probs(VP9_COMMON* const cm, vp9_reader *r) {
   int i, j;
-  for (j = 0; j < VP9_SWITCHABLE_FILTERS + 1; ++j)
-    for (i = 0; i < VP9_SWITCHABLE_FILTERS - 1; ++i)
-      cm->fc.switchable_interp_prob[j][i] = vp9_read_prob(r);
+  for (j = 0; j <= VP9_SWITCHABLE_FILTERS; ++j)
+    for (i = 0; i < VP9_SWITCHABLE_FILTERS - 1; ++i) {
+      if (vp9_read(r, VP9_DEF_UPDATE_PROB)) {
+        cm->fc.switchable_interp_prob[j][i] =
+            // vp9_read_prob(r);
+            vp9_read_prob_diff_update(r, cm->fc.switchable_interp_prob[j][i]);
+      }
+    }
+}
+
+static void read_inter_mode_probs(VP9_COMMON *const cm, vp9_reader *r) {
+  int i, j;
+  for (i = 0; i < INTER_MODE_CONTEXTS; ++i)
+    for (j = 0; j < VP9_INTER_MODES - 1; ++j) {
+      if (vp9_read(r, VP9_DEF_UPDATE_PROB)) {
+        // cm->fc.inter_mode_probs[i][j] = vp9_read_prob(r);
+        cm->fc.inter_mode_probs[i][j] =
+            vp9_read_prob_diff_update(r, cm->fc.inter_mode_probs[i][j]);
+      }
+    }
 }
 
 static INLINE COMPPREDMODE_TYPE read_comp_pred_mode(vp9_reader *r) {
@@ -367,32 +349,62 @@
     MACROBLOCKD *const xd = &pbi->mb;
     int i, j;
 
+    read_inter_mode_probs(cm, r);
+
     if (cm->mcomp_filter_type == SWITCHABLE)
-      read_switchable_interp_probs(pbi, r);
+      read_switchable_interp_probs(cm, r);
 
-    // Baseline probabilities for decoding reference frame
-    cm->prob_intra_coded = vp9_read_prob(r);
-    cm->prob_last_coded  = vp9_read_prob(r);
-    cm->prob_gf_coded    = vp9_read_prob(r);
+    for (i = 0; i < INTRA_INTER_CONTEXTS; i++) {
+      if (vp9_read(r, VP9_DEF_UPDATE_PROB))
+        cm->fc.intra_inter_prob[i] =
+            vp9_read_prob_diff_update(r, cm->fc.intra_inter_prob[i]);
+    }
 
-    // Computes a modified set of probabilities for use when reference
-    // frame prediction fails.
-    vp9_compute_mod_refprobs(cm);
+    if (cm->allow_comp_inter_inter) {
+      cm->comp_pred_mode = read_comp_pred_mode(r);
+      if (cm->comp_pred_mode == HYBRID_PREDICTION)
+        for (i = 0; i < COMP_INTER_CONTEXTS; i++)
+          if (vp9_read(r, VP9_DEF_UPDATE_PROB))
+            cm->fc.comp_inter_prob[i] =
+                vp9_read_prob_diff_update(r, cm->fc.comp_inter_prob[i]);
+    } else {
+      cm->comp_pred_mode = SINGLE_PREDICTION_ONLY;
+    }
 
-    cm->comp_pred_mode = read_comp_pred_mode(r);
-    if (cm->comp_pred_mode == HYBRID_PREDICTION)
-      for (i = 0; i < COMP_PRED_CONTEXTS; i++)
-        cm->prob_comppred[i] = vp9_read_prob(r);
+    if (cm->comp_pred_mode != COMP_PREDICTION_ONLY)
+      for (i = 0; i < REF_CONTEXTS; i++) {
+        if (vp9_read(r, VP9_DEF_UPDATE_PROB))
+          cm->fc.single_ref_prob[i][0] =
+              vp9_read_prob_diff_update(r, cm->fc.single_ref_prob[i][0]);
+        if (vp9_read(r, VP9_DEF_UPDATE_PROB))
+          cm->fc.single_ref_prob[i][1] =
+              vp9_read_prob_diff_update(r, cm->fc.single_ref_prob[i][1]);
+      }
+
+    if (cm->comp_pred_mode != SINGLE_PREDICTION_ONLY)
+      for (i = 0; i < REF_CONTEXTS; i++)
+        if (vp9_read(r, VP9_DEF_UPDATE_PROB))
+          cm->fc.comp_ref_prob[i] =
+              vp9_read_prob_diff_update(r, cm->fc.comp_ref_prob[i]);
 
     // VP9_INTRA_MODES
-    if (vp9_read_bit(r))
-      for (i = 0; i < VP9_INTRA_MODES - 1; ++i)
-        cm->fc.y_mode_prob[i] = vp9_read_prob(r);
-
-    for (j = 0; j < NUM_PARTITION_CONTEXTS; ++j)
-      if (vp9_read_bit(r))
-        for (i = 0; i < PARTITION_TYPES - 1; ++i)
-          cm->fc.partition_prob[j][i] = vp9_read_prob(r);
+    for (j = 0; j < BLOCK_SIZE_GROUPS; j++) {
+      for (i = 0; i < VP9_INTRA_MODES - 1; ++i) {
+        if (vp9_read(r, VP9_DEF_UPDATE_PROB)) {
+          cm->fc.y_mode_prob[j][i] =
+              vp9_read_prob_diff_update(r, cm->fc.y_mode_prob[j][i]);
+        }
+      }
+    }
+    for (j = 0; j < NUM_PARTITION_CONTEXTS; ++j) {
+      for (i = 0; i < PARTITION_TYPES - 1; ++i) {
+        if (vp9_read(r, VP9_DEF_UPDATE_PROB)) {
+          cm->fc.partition_prob[INTER_FRAME][j][i] =
+              vp9_read_prob_diff_update(r,
+                  cm->fc.partition_prob[INTER_FRAME][j][i]);
+        }
+      }
+    }
 
     read_nmvprobs(r, nmvc, xd->allow_high_precision_mv);
   }
@@ -474,6 +486,9 @@
   const int index = treed_read(r, vp9_switchable_interp_tree,
                                vp9_get_pred_probs(&pbi->common, &pbi->mb,
                                                   PRED_SWITCHABLE_INTERP));
+  ++pbi->common.fc.switchable_interp_count
+                [vp9_get_pred_context(
+                    &pbi->common, &pbi->mb, PRED_SWITCHABLE_INTERP)][index];
   return vp9_switchable_interp[index];
 }
 
@@ -495,7 +510,7 @@
 
   mbmi->need_to_clamp_mvs = 0;
   mbmi->need_to_clamp_secondmv = 0;
-  mbmi->second_ref_frame = NONE;
+  mbmi->ref_frame[1] = NONE;
 
   // Make sure the MACROBLOCKD mode info pointer is pointed at the
   // correct entry for the current macroblock.
@@ -521,14 +536,14 @@
     mbmi->mb_skip_coeff = vp9_read(r, vp9_get_pred_prob(cm, xd, PRED_MBSKIP));
 
   // Read the reference frame
-  mbmi->ref_frame = read_ref_frame(pbi, r, mbmi->segment_id);
+  mbmi->ref_frame[0] = vp9_read(r, vp9_get_pred_prob(cm, xd, PRED_INTRA_INTER));
+  cm->fc.intra_inter_count[vp9_get_pred_context(cm, xd, PRED_INTRA_INTER)]
+                          [mbmi->ref_frame[0] != INTRA_FRAME]++;
 
   if (cm->txfm_mode == TX_MODE_SELECT &&
-      (mbmi->mb_skip_coeff == 0 || mbmi->ref_frame == INTRA_FRAME) &&
+      (mbmi->mb_skip_coeff == 0 || mbmi->ref_frame[0] == INTRA_FRAME) &&
       bsize >= BLOCK_SIZE_SB8X8) {
-    const int allow_16x16 = bsize >= BLOCK_SIZE_MB16X16;
-    const int allow_32x32 = bsize >= BLOCK_SIZE_SB32X32;
-    mbmi->txfm_size = select_txfm_size(cm, r, allow_16x16, allow_32x32);
+    mbmi->txfm_size = select_txfm_size(cm, r, bsize);
   } else if (bsize >= BLOCK_SIZE_SB32X32 &&
              cm->txfm_mode >= ALLOW_32X32) {
     mbmi->txfm_size = TX_32X32;
@@ -542,11 +557,12 @@
   }
 
   // If reference frame is an Inter frame
-  if (mbmi->ref_frame) {
+  if (mbmi->ref_frame[0] != INTRA_FRAME) {
     int_mv nearest, nearby, best_mv;
     int_mv nearest_second, nearby_second, best_mv_second;
-    vp9_prob mv_ref_p[VP9_MVREFS - 1];
-    const MV_REFERENCE_FRAME ref_frame = mbmi->ref_frame;
+    vp9_prob mv_ref_p[VP9_INTER_MODES - 1];
+
+    read_ref_frame(pbi, r, mbmi->segment_id, mbmi->ref_frame);
 
     {
 #ifdef DEC_DEBUG
@@ -554,25 +570,27 @@
         printf("%d %d\n", xd->mode_info_context->mbmi.mv[0].as_mv.row,
                xd->mode_info_context->mbmi.mv[0].as_mv.col);
 #endif
-      vp9_find_mv_refs(cm, xd, mi, xd->prev_mode_info_context, ref_frame,
-                       mbmi->ref_mvs[ref_frame], cm->ref_frame_sign_bias);
+      vp9_find_mv_refs(cm, xd, mi, xd->prev_mode_info_context,
+                       mbmi->ref_frame[0], mbmi->ref_mvs[mbmi->ref_frame[0]],
+                       cm->ref_frame_sign_bias);
 
-      vp9_mv_ref_probs(cm, mv_ref_p, mbmi->mb_mode_context[ref_frame]);
+      vp9_mv_ref_probs(cm, mv_ref_p, mbmi->mb_mode_context[mbmi->ref_frame[0]]);
 
       // If the segment level skip mode enabled
       if (vp9_segfeature_active(xd, mbmi->segment_id, SEG_LVL_SKIP)) {
         mbmi->mode = ZEROMV;
       } else if (bsize >= BLOCK_SIZE_SB8X8) {
         mbmi->mode = read_sb_mv_ref(r, mv_ref_p);
-        vp9_accum_mv_refs(cm, mbmi->mode, mbmi->mb_mode_context[ref_frame]);
+        vp9_accum_mv_refs(cm, mbmi->mode,
+                          mbmi->mb_mode_context[mbmi->ref_frame[0]]);
       }
 
       if (bsize < BLOCK_SIZE_SB8X8 || mbmi->mode != ZEROMV) {
         vp9_find_best_ref_mvs(xd,
-                              mbmi->ref_mvs[ref_frame],
+                              mbmi->ref_mvs[mbmi->ref_frame[0]],
                               &nearest, &nearby);
 
-        best_mv.as_int = mbmi->ref_mvs[ref_frame][0].as_int;
+        best_mv.as_int = mbmi->ref_mvs[mbmi->ref_frame[0]][0].as_int;
       }
 
 #ifdef DEC_DEBUG
@@ -587,33 +605,18 @@
                               ? read_switchable_filter_type(pbi, r)
                               : cm->mcomp_filter_type;
 
-    if (cm->comp_pred_mode == COMP_PREDICTION_ONLY ||
-        (cm->comp_pred_mode == HYBRID_PREDICTION &&
-         vp9_read(r, vp9_get_pred_prob(cm, xd, PRED_COMP)))) {
-      /* Since we have 3 reference frames, we can only have 3 unique
-       * combinations of combinations of 2 different reference frames
-       * (A-G, G-L or A-L). In the bitstream, we use this to simply
-       * derive the second reference frame from the first reference
-       * frame, by saying it's the next one in the enumerator, and
-       * if that's > n_refs, then the second reference frame is the
-       * first one in the enumerator. */
-      mbmi->second_ref_frame = mbmi->ref_frame + 1;
-      if (mbmi->second_ref_frame == 4)
-        mbmi->second_ref_frame = 1;
-      if (mbmi->second_ref_frame > 0) {
-        const MV_REFERENCE_FRAME second_ref_frame = mbmi->second_ref_frame;
+    if (mbmi->ref_frame[1] > INTRA_FRAME) {
+      vp9_find_mv_refs(cm, xd, mi, xd->prev_mode_info_context,
+                       mbmi->ref_frame[1],
+                       mbmi->ref_mvs[mbmi->ref_frame[1]],
+                       cm->ref_frame_sign_bias);
 
-        vp9_find_mv_refs(cm, xd, mi, xd->prev_mode_info_context,
-                         second_ref_frame, mbmi->ref_mvs[second_ref_frame],
-                         cm->ref_frame_sign_bias);
-
-        if (bsize < BLOCK_SIZE_SB8X8 || mbmi->mode != ZEROMV) {
-          vp9_find_best_ref_mvs(xd,
-                                mbmi->ref_mvs[second_ref_frame],
-                                &nearest_second,
-                                &nearby_second);
-          best_mv_second.as_int = mbmi->ref_mvs[second_ref_frame][0].as_int;
-        }
+      if (bsize < BLOCK_SIZE_SB8X8 || mbmi->mode != ZEROMV) {
+        vp9_find_best_ref_mvs(xd,
+                              mbmi->ref_mvs[mbmi->ref_frame[1]],
+                              &nearest_second,
+                              &nearby_second);
+        best_mv_second.as_int = mbmi->ref_mvs[mbmi->ref_frame[1]][0].as_int;
       }
     }
 
@@ -628,9 +631,10 @@
           j = idy * 2 + idx;
 
           blockmode = read_sb_mv_ref(r, mv_ref_p);
-          vp9_accum_mv_refs(cm, blockmode, mbmi->mb_mode_context[ref_frame]);
+          vp9_accum_mv_refs(cm, blockmode,
+                            mbmi->mb_mode_context[mbmi->ref_frame[0]]);
           if (blockmode == NEARESTMV || blockmode == NEARMV) {
-            MV_REFERENCE_FRAME rf2 = mbmi->second_ref_frame;
+            MV_REFERENCE_FRAME rf2 = mbmi->ref_frame[1];
             vp9_append_sub8x8_mvs_for_idx(cm, xd, &nearest, &nearby, j, 0);
             if (rf2 > 0) {
               vp9_append_sub8x8_mvs_for_idx(cm, xd,  &nearest_second,
@@ -643,7 +647,7 @@
               decode_mv(r, &blockmv.as_mv, &best_mv.as_mv, nmvc,
                          &cm->fc.NMVcount, xd->allow_high_precision_mv);
 
-              if (mbmi->second_ref_frame > 0)
+              if (mbmi->ref_frame[1] > 0)
                 decode_mv(r, &secondmv.as_mv, &best_mv_second.as_mv, nmvc,
                           &cm->fc.NMVcount, xd->allow_high_precision_mv);
 
@@ -653,7 +657,7 @@
               break;
             case NEARESTMV:
               blockmv.as_int = nearest.as_int;
-              if (mbmi->second_ref_frame > 0)
+              if (mbmi->ref_frame[1] > 0)
                 secondmv.as_int = nearest_second.as_int;
 #ifdef VPX_MODE_COUNT
               vp9_mv_cont_count[mv_contz][0]++;
@@ -661,7 +665,7 @@
               break;
             case NEARMV:
               blockmv.as_int = nearby.as_int;
-              if (mbmi->second_ref_frame > 0)
+              if (mbmi->ref_frame[1] > 0)
                 secondmv.as_int = nearby_second.as_int;
 #ifdef VPX_MODE_COUNT
               vp9_mv_cont_count[mv_contz][1]++;
@@ -669,7 +673,7 @@
               break;
             case ZEROMV:
               blockmv.as_int = 0;
-              if (mbmi->second_ref_frame > 0)
+              if (mbmi->ref_frame[1] > 0)
                 secondmv.as_int = 0;
 #ifdef VPX_MODE_COUNT
               vp9_mv_cont_count[mv_contz][2]++;
@@ -679,7 +683,7 @@
               break;
           }
           mi->bmi[j].as_mv[0].as_int = blockmv.as_int;
-          if (mbmi->second_ref_frame > 0)
+          if (mbmi->ref_frame[1] > 0)
             mi->bmi[j].as_mv[1].as_int = secondmv.as_int;
 
           for (i = 1; i < bh; ++i)
@@ -700,7 +704,7 @@
                                             mb_to_right_edge,
                                             mb_to_top_edge,
                                             mb_to_bottom_edge);
-          if (mbmi->second_ref_frame > 0)
+          if (mbmi->ref_frame[1] > 0)
             assign_and_clamp_mv(mv1, &nearby_second, mb_to_left_edge,
                                                      mb_to_right_edge,
                                                      mb_to_top_edge,
@@ -713,7 +717,7 @@
                                              mb_to_right_edge,
                                              mb_to_top_edge,
                                              mb_to_bottom_edge);
-          if (mbmi->second_ref_frame > 0)
+          if (mbmi->ref_frame[1] > 0)
             assign_and_clamp_mv(mv1, &nearest_second, mb_to_left_edge,
                                                       mb_to_right_edge,
                                                       mb_to_top_edge,
@@ -722,7 +726,7 @@
 
         case ZEROMV:
           mv0->as_int = 0;
-          if (mbmi->second_ref_frame > 0)
+          if (mbmi->ref_frame[1] > 0)
             mv1->as_int = 0;
           break;
 
@@ -735,7 +739,7 @@
                                                     mb_to_top_edge,
                                                     mb_to_bottom_edge);
 
-          if (mbmi->second_ref_frame > 0) {
+          if (mbmi->ref_frame[1] > 0) {
             decode_mv(r, &mv1->as_mv, &best_mv_second.as_mv, nmvc,
                       &cm->fc.NMVcount, xd->allow_high_precision_mv);
             mbmi->need_to_clamp_secondmv = check_mv_bounds(mv1,
@@ -757,16 +761,19 @@
     mv0->as_int = 0;
 
     if (bsize >= BLOCK_SIZE_SB8X8) {
-      mbmi->mode = read_intra_mode(r, cm->fc.y_mode_prob);
-      cm->fc.y_mode_counts[mbmi->mode]++;
+      const BLOCK_SIZE_TYPE bsize = xd->mode_info_context->mbmi.sb_type;
+      const int bwl = b_width_log2(bsize), bhl = b_height_log2(bsize);
+      const int bsl = MIN(bwl, bhl);
+      mbmi->mode = read_intra_mode(r, cm->fc.y_mode_prob[MIN(3, bsl)]);
+      cm->fc.y_mode_counts[MIN(3, bsl)][mbmi->mode]++;
     } else {
       int idx, idy;
       for (idy = 0; idy < 2; idy += bh) {
         for (idx = 0; idx < 2; idx += bw) {
           int ib = idy * 2 + idx, k;
-          int m = read_intra_mode(r, cm->fc.y_mode_prob);
+          int m = read_intra_mode(r, cm->fc.y_mode_prob[0]);
           mi->bmi[ib].as_mode.first = m;
-          cm->fc.y_mode_counts[m]++;
+          cm->fc.y_mode_counts[0][m]++;
           for (k = 1; k < bh; ++k)
             mi->bmi[ib + k * 2].as_mode.first = m;
           for (k = 1; k < bw; ++k)
diff --git a/vp9/decoder/vp9_decodframe.c b/vp9/decoder/vp9_decodframe.c
index 5c03061..aacdad5 100644
--- a/vp9/decoder/vp9_decodframe.c
+++ b/vp9/decoder/vp9_decodframe.c
@@ -57,11 +57,16 @@
     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);
+      int i;
+      for (i = 0; i < TX_SIZE_PROBS; ++i) {
+        if (vp9_read(r, VP9_DEF_UPDATE_PROB))
+           pc->fc.tx_probs[i] =
+               vp9_read_prob_diff_update(r, pc->fc.tx_probs[i]);
+      }
+    } else {
+      vpx_memcpy(pc->fc.tx_probs, vp9_default_tx_probs,
+                 sizeof(vp9_default_tx_probs));
     }
   }
 }
@@ -117,13 +122,8 @@
   return word;
 }
 
-static int decode_unsigned_max(vp9_reader *r, int max) {
-  int data = 0, bit = 0, lmax = max;
-
-  while (lmax) {
-    data |= vp9_read_bit(r) << bit++;
-    lmax >>= 1;
-  }
+static int decode_unsigned_max(struct vp9_read_bit_buffer *rb, int max) {
+  const int data = vp9_rb_read_literal(rb, get_unsigned_bits(max));
   return data > max ? max : data;
 }
 
@@ -153,7 +153,7 @@
   }
 }
 
-static vp9_prob read_prob_diff_update(vp9_reader *r, int oldp) {
+vp9_prob vp9_read_prob_diff_update(vp9_reader *r, int oldp) {
   int delp = decode_term_subexp(r, SUBEXP_PARAM, 255);
   return (vp9_prob)inv_remap_prob(delp, oldp);
 }
@@ -240,6 +240,7 @@
   mode = plane == 0? xd->mode_info_context->mbmi.mode:
                      xd->mode_info_context->mbmi.uv_mode;
 
+
   if (xd->mode_info_context->mbmi.sb_type < BLOCK_SIZE_SB8X8 && plane == 0) {
     assert(bsize == BLOCK_SIZE_SB8X8);
     b_mode = xd->mode_info_context->bmi[raster_block].as_mode.first;
@@ -247,6 +248,10 @@
     b_mode = mode;
   }
 
+  if (xd->mb_to_right_edge < 0 || xd->mb_to_bottom_edge < 0) {
+    extend_for_intra(xd, plane, block, bsize, ss_txfrm_size);
+  }
+
   plane_b_size = b_width_log2(bsize) - xd->plane[plane].subsampling_x;
   vp9_predict_intra_block(xd, tx_ib, plane_b_size, tx_size,
                           b_mode, dst, xd->plane[plane].dst.stride);
@@ -281,7 +286,7 @@
                         vp9_reader *r, BLOCK_SIZE_TYPE bsize) {
   MB_MODE_INFO *const mbmi = &xd->mode_info_context->mbmi;
 
-  assert(mbmi->ref_frame != INTRA_FRAME);
+  assert(mbmi->ref_frame[0] != INTRA_FRAME);
 
   if (pbi->common.frame_type != KEY_FRAME)
     vp9_setup_interp_filters(xd, mbmi->interp_filter, &pbi->common);
@@ -334,7 +339,7 @@
   const int mis = pc->mode_info_stride;
 
   assert(mbmi->sb_type == bsize);
-  assert(mbmi->ref_frame != INTRA_FRAME);
+  assert(mbmi->ref_frame[0] != INTRA_FRAME);
 
   if (pbi->common.frame_type != KEY_FRAME)
     vp9_setup_interp_filters(xd, mbmi->interp_filter, pc);
@@ -401,22 +406,22 @@
   MACROBLOCKD *const xd = &pbi->mb;
   MB_MODE_INFO *const mbmi = &xd->mode_info_context->mbmi;
 
-  if (mbmi->ref_frame > INTRA_FRAME) {
+  if (mbmi->ref_frame[0] > INTRA_FRAME) {
     // Select the appropriate reference frame for this MB
-    const int fb_idx = cm->active_ref_idx[mbmi->ref_frame - 1];
+    const int fb_idx = cm->active_ref_idx[mbmi->ref_frame[0] - 1];
     const YV12_BUFFER_CONFIG *cfg = &cm->yv12_fb[fb_idx];
-    xd->scale_factor[0]    = cm->active_ref_scale[mbmi->ref_frame - 1];
-    xd->scale_factor_uv[0] = cm->active_ref_scale[mbmi->ref_frame - 1];
+    xd->scale_factor[0]    = cm->active_ref_scale[mbmi->ref_frame[0] - 1];
+    xd->scale_factor_uv[0] = cm->active_ref_scale[mbmi->ref_frame[0] - 1];
     setup_pre_planes(xd, cfg, NULL, mi_row, mi_col,
                      xd->scale_factor, xd->scale_factor_uv);
     xd->corrupted |= cfg->corrupted;
 
-    if (mbmi->second_ref_frame > INTRA_FRAME) {
+    if (mbmi->ref_frame[1] > INTRA_FRAME) {
       // Select the appropriate reference frame for this MB
-      const int second_fb_idx = cm->active_ref_idx[mbmi->second_ref_frame - 1];
+      const int second_fb_idx = cm->active_ref_idx[mbmi->ref_frame[1] - 1];
       const YV12_BUFFER_CONFIG *second_cfg = &cm->yv12_fb[second_fb_idx];
-      xd->scale_factor[1]    = cm->active_ref_scale[mbmi->second_ref_frame - 1];
-      xd->scale_factor_uv[1] = cm->active_ref_scale[mbmi->second_ref_frame - 1];
+      xd->scale_factor[1]    = cm->active_ref_scale[mbmi->ref_frame[1] - 1];
+      xd->scale_factor_uv[1] = cm->active_ref_scale[mbmi->ref_frame[1] - 1];
       setup_pre_planes(xd, NULL, second_cfg, mi_row, mi_col,
                        xd->scale_factor, xd->scale_factor_uv);
       xd->corrupted |= second_cfg->corrupted;
@@ -435,7 +440,7 @@
   vp9_decode_mb_mode_mv(pbi, xd, mi_row, mi_col, r);
   set_refs(pbi, mi_row, mi_col);
 
-  if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME)
+  if (xd->mode_info_context->mbmi.ref_frame[0] == INTRA_FRAME)
     decode_sb_intra(pbi, xd, mi_row, mi_col, r, (bsize < BLOCK_SIZE_SB8X8) ?
                                      BLOCK_SIZE_SB8X8 : bsize);
   else if (bsize < BLOCK_SIZE_SB8X8)
@@ -469,7 +474,7 @@
     xd->above_seg_context = pc->above_seg_context + mi_col;
     pl = partition_plane_context(xd, bsize);
     partition = treed_read(r, vp9_partition_tree,
-                           pc->fc.partition_prob[pl]);
+                           pc->fc.partition_prob[pc->frame_type][pl]);
     pc->fc.partition_counts[pl][partition]++;
   }
 
@@ -530,25 +535,6 @@
                        "Failed to allocate bool decoder %d", 1);
 }
 
-static void init_frame(VP9D_COMP *pbi) {
-  VP9_COMMON *const pc = &pbi->common;
-  MACROBLOCKD *const xd = &pbi->mb;
-
-  if (pc->frame_type == KEY_FRAME) {
-    vp9_setup_past_independence(pc, xd);
-    // All buffers are implicitly updated on key frames.
-    pbi->refresh_frame_flags = (1 << NUM_REF_FRAMES) - 1;
-  } else if (pc->error_resilient_mode) {
-    vp9_setup_past_independence(pc, xd);
-  }
-
-  xd->mode_info_context = pc->mi;
-  xd->prev_mode_info_context = pc->prev_mi;
-  xd->frame_type = pc->frame_type;
-  xd->mode_info_context->mbmi.mode = DC_PRED;
-  xd->mode_info_stride = pc->mode_info_stride;
-}
-
 static void read_coef_probs_common(FRAME_CONTEXT *fc, TX_SIZE tx_size,
                                    vp9_reader *r) {
   const int entropy_nodes_update = UNCONSTRAINED_NODES;
@@ -569,7 +555,7 @@
               vp9_prob *const p = coef_probs[i][j][k][l] + m;
 
               if (vp9_read(r, vp9_coef_update_prob[m])) {
-                *p = read_prob_diff_update(r, *p);
+                *p = vp9_read_prob_diff_update(r, *p);
               }
             }
           }
@@ -580,65 +566,68 @@
 }
 
 static void read_coef_probs(VP9D_COMP *pbi, vp9_reader *r) {
-  const TXFM_MODE mode = pbi->common.txfm_mode;
+  const TXFM_MODE txfm_mode = pbi->common.txfm_mode;
   FRAME_CONTEXT *const fc = &pbi->common.fc;
 
   read_coef_probs_common(fc, TX_4X4, r);
 
-  if (mode > ONLY_4X4)
+  if (txfm_mode > ONLY_4X4)
     read_coef_probs_common(fc, TX_8X8, r);
 
-  if (mode > ALLOW_8X8)
+  if (txfm_mode > ALLOW_8X8)
     read_coef_probs_common(fc, TX_16X16, r);
 
-  if (mode > ALLOW_16X16)
+  if (txfm_mode > ALLOW_16X16)
     read_coef_probs_common(fc, TX_32X32, r);
 }
 
-static void setup_segmentation(VP9_COMMON *pc, MACROBLOCKD *xd, vp9_reader *r) {
+static void setup_segmentation(VP9D_COMP *pbi, struct vp9_read_bit_buffer *rb) {
   int i, j;
 
+  VP9_COMMON *const cm = &pbi->common;
+  MACROBLOCKD *const xd = &pbi->mb;
+
   xd->update_mb_segmentation_map = 0;
   xd->update_mb_segmentation_data = 0;
 
-  xd->segmentation_enabled = vp9_read_bit(r);
+  xd->segmentation_enabled = vp9_rb_read_bit(rb);
   if (!xd->segmentation_enabled)
     return;
 
   // Segmentation map update
-  xd->update_mb_segmentation_map = vp9_read_bit(r);
+  xd->update_mb_segmentation_map = vp9_rb_read_bit(rb);
   if (xd->update_mb_segmentation_map) {
     for (i = 0; i < MB_SEG_TREE_PROBS; i++)
-      xd->mb_segment_tree_probs[i] = vp9_read_bit(r) ? vp9_read_prob(r)
-                                                     : MAX_PROB;
+      xd->mb_segment_tree_probs[i] = vp9_rb_read_bit(rb) ?
+                                         vp9_rb_read_literal(rb, 8) : MAX_PROB;
 
-    pc->temporal_update = vp9_read_bit(r);
-    if (pc->temporal_update) {
+    cm->temporal_update = vp9_rb_read_bit(rb);
+    if (cm->temporal_update) {
       for (i = 0; i < PREDICTION_PROBS; i++)
-        pc->segment_pred_probs[i] = vp9_read_bit(r) ? vp9_read_prob(r)
-                                                    : MAX_PROB;
+        cm->segment_pred_probs[i] = vp9_rb_read_bit(rb) ?
+                                        vp9_rb_read_literal(rb, 8) : MAX_PROB;
     } else {
       for (i = 0; i < PREDICTION_PROBS; i++)
-        pc->segment_pred_probs[i] = MAX_PROB;
+        cm->segment_pred_probs[i] = MAX_PROB;
     }
   }
 
   // Segmentation data update
-  xd->update_mb_segmentation_data = vp9_read_bit(r);
+  xd->update_mb_segmentation_data = vp9_rb_read_bit(rb);
   if (xd->update_mb_segmentation_data) {
-    xd->mb_segment_abs_delta = vp9_read_bit(r);
+    xd->mb_segment_abs_delta = vp9_rb_read_bit(rb);
 
     vp9_clearall_segfeatures(xd);
 
     for (i = 0; i < MAX_MB_SEGMENTS; i++) {
       for (j = 0; j < SEG_LVL_MAX; j++) {
         int data = 0;
-        const int feature_enabled = vp9_read_bit(r);
+        const int feature_enabled = vp9_rb_read_bit(rb);
         if (feature_enabled) {
           vp9_enable_segfeature(xd, i, j);
-          data = decode_unsigned_max(r, vp9_seg_feature_data_max(j));
+          data = decode_unsigned_max(rb, vp9_seg_feature_data_max(j));
           if (vp9_is_segfeature_signed(j))
-            data = vp9_read_and_apply_sign(r, data);
+            data = vp9_rb_read_bit(rb) ? -data : data;
         }
         vp9_set_segdata(xd, i, j, data);
       }
@@ -646,22 +635,6 @@
   }
 }
 
-static void setup_pred_probs(VP9_COMMON *pc, vp9_reader *r) {
-  // Read common prediction model status flag probability updates for the
-  // reference frame
-  if (pc->frame_type == KEY_FRAME) {
-    // Set the prediction probabilities to defaults
-    pc->ref_pred_probs[0] = DEFAULT_PRED_PROB_0;
-    pc->ref_pred_probs[1] = DEFAULT_PRED_PROB_1;
-    pc->ref_pred_probs[2] = DEFAULT_PRED_PROB_2;
-  } else {
-    int i;
-    for (i = 0; i < PREDICTION_PROBS; ++i)
-      if (vp9_read_bit(r))
-        pc->ref_pred_probs[i] = vp9_read_prob(r);
-  }
-}
-
 static void setup_loopfilter(VP9D_COMP *pbi, struct vp9_read_bit_buffer *rb) {
   VP9_COMMON *const cm = &pbi->common;
   MACROBLOCKD *const xd = &pbi->mb;
@@ -706,19 +679,36 @@
 }
 
 static void setup_quantization(VP9D_COMP *pbi, struct vp9_read_bit_buffer *rb) {
+  MACROBLOCKD *const xd = &pbi->mb;
   VP9_COMMON *const cm = &pbi->common;
   int update = 0;
+
   cm->base_qindex = vp9_rb_read_literal(rb, QINDEX_BITS);
   update |= read_delta_q(rb, &cm->y_dc_delta_q);
   update |= read_delta_q(rb, &cm->uv_dc_delta_q);
   update |= read_delta_q(rb, &cm->uv_ac_delta_q);
   if (update)
     vp9_init_dequantizer(cm);
+
+  xd->lossless = cm->base_qindex == 0 &&
+                 cm->y_dc_delta_q == 0 &&
+                 cm->uv_dc_delta_q == 0 &&
+                 cm->uv_ac_delta_q == 0;
+  if (xd->lossless) {
+    xd->itxm_add          = vp9_idct_add_lossless_c;
+    xd->itxm_add_y_block  = vp9_idct_add_y_block_lossless_c;
+    xd->itxm_add_uv_block = vp9_idct_add_uv_block_lossless_c;
+  } else {
+    xd->itxm_add          = vp9_idct_add;
+    xd->itxm_add_y_block  = vp9_idct_add_y_block;
+    xd->itxm_add_uv_block = vp9_idct_add_uv_block;
+  }
 }
 
-static INTERPOLATIONFILTERTYPE read_mcomp_filter_type(vp9_reader *r) {
-  return vp9_read_bit(r) ? SWITCHABLE
-                         : vp9_read_literal(r, 2);
+static INTERPOLATIONFILTERTYPE read_interp_filter_type(
+    struct vp9_read_bit_buffer *rb) {
+  return vp9_rb_read_bit(rb) ? SWITCHABLE
+                             : vp9_rb_read_literal(rb, 2);
 }
 
 static void read_frame_size(VP9_COMMON *cm,
@@ -757,8 +747,8 @@
       if (vp9_alloc_frame_buffers(pc, width, height))
         vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
                            "Failed to allocate frame buffers");
-        pbi->initial_width = width;
-        pbi->initial_height = height;
+      pbi->initial_width = width;
+      pbi->initial_height = height;
     } else {
       if (width > pbi->initial_width)
         vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
@@ -776,22 +766,41 @@
 
     vp9_update_frame_size(pc);
   }
+
+  vp9_realloc_frame_buffer(&pc->yv12_fb[pc->new_fb_idx], pc->width, pc->height,
+                           pc->subsampling_x, pc->subsampling_y,
+                           VP9BORDERINPIXELS);
 }
 
 static void update_frame_context(FRAME_CONTEXT *fc) {
   vp9_copy(fc->pre_coef_probs, fc->coef_probs);
   vp9_copy(fc->pre_y_mode_prob, fc->y_mode_prob);
   vp9_copy(fc->pre_uv_mode_prob, fc->uv_mode_prob);
-  vp9_copy(fc->pre_partition_prob, fc->partition_prob);
+  vp9_copy(fc->pre_partition_prob, fc->partition_prob[1]);
+  vp9_copy(fc->pre_intra_inter_prob, fc->intra_inter_prob);
+  vp9_copy(fc->pre_comp_inter_prob, fc->comp_inter_prob);
+  vp9_copy(fc->pre_single_ref_prob, fc->single_ref_prob);
+  vp9_copy(fc->pre_comp_ref_prob, fc->comp_ref_prob);
   fc->pre_nmvc = fc->nmvc;
+  vp9_copy(fc->pre_switchable_interp_prob, fc->switchable_interp_prob);
+  vp9_copy(fc->pre_inter_mode_probs, fc->inter_mode_probs);
+  vp9_copy(fc->pre_tx_probs, fc->tx_probs);
 
   vp9_zero(fc->coef_counts);
   vp9_zero(fc->eob_branch_counts);
   vp9_zero(fc->y_mode_counts);
   vp9_zero(fc->uv_mode_counts);
   vp9_zero(fc->NMVcount);
-  vp9_zero(fc->mv_ref_ct);
+  vp9_zero(fc->inter_mode_counts);
   vp9_zero(fc->partition_counts);
+  vp9_zero(fc->switchable_interp_count);
+  vp9_zero(fc->intra_inter_count);
+  vp9_zero(fc->comp_inter_count);
+  vp9_zero(fc->single_ref_count);
+  vp9_zero(fc->comp_ref_count);
+  vp9_zero(fc->tx_count_8x8p);
+  vp9_zero(fc->tx_count_16x16p);
+  vp9_zero(fc->tx_count_32x32p);
 }
 
 static void decode_tile(VP9D_COMP *pbi, vp9_reader *r) {
@@ -809,27 +818,33 @@
   }
 }
 
-static void decode_tiles(VP9D_COMP *pbi,
-                         const uint8_t *data, int first_partition_size,
-                         vp9_reader *header_bc, vp9_reader *residual_bc) {
-  VP9_COMMON *const pc = &pbi->common;
+static void setup_tile_info(VP9_COMMON *cm, struct vp9_read_bit_buffer *rb) {
+  int delta_log2_tiles;
 
-  const uint8_t *data_ptr = data + first_partition_size;
-  int tile_row, tile_col, delta_log2_tiles;
-
-  vp9_get_tile_n_bits(pc, &pc->log2_tile_columns, &delta_log2_tiles);
+  vp9_get_tile_n_bits(cm, &cm->log2_tile_columns, &delta_log2_tiles);
   while (delta_log2_tiles--) {
-    if (vp9_read_bit(header_bc)) {
-      pc->log2_tile_columns++;
+    if (vp9_rb_read_bit(rb)) {
+      cm->log2_tile_columns++;
     } else {
       break;
     }
   }
-  pc->log2_tile_rows = vp9_read_bit(header_bc);
-  if (pc->log2_tile_rows)
-    pc->log2_tile_rows += vp9_read_bit(header_bc);
-  pc->tile_columns = 1 << pc->log2_tile_columns;
-  pc->tile_rows    = 1 << pc->log2_tile_rows;
+
+  cm->log2_tile_rows = vp9_rb_read_bit(rb);
+  if (cm->log2_tile_rows)
+    cm->log2_tile_rows += vp9_rb_read_bit(rb);
+
+  cm->tile_columns = 1 << cm->log2_tile_columns;
+  cm->tile_rows    = 1 << cm->log2_tile_rows;
+}
+
+static void decode_tiles(VP9D_COMP *pbi,
+                         const uint8_t *data, size_t first_partition_size,
+                         vp9_reader *residual_bc) {
+  VP9_COMMON *const pc = &pbi->common;
+
+  const uint8_t *data_ptr = data + first_partition_size;
+  int tile_row, tile_col;
 
   // Note: this memset assumes above_context[0], [1] and [2]
   // are allocated as part of the same buffer.
@@ -901,39 +916,56 @@
   vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME, "Truncated packet");
 }
 
+#define RESERVED \
+  if (vp9_rb_read_bit(rb)) \
+      vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM, \
+                         "Reserved bit must be unset")
+
 size_t read_uncompressed_header(VP9D_COMP *pbi,
                                 struct vp9_read_bit_buffer *rb) {
   VP9_COMMON *const cm = &pbi->common;
+  MACROBLOCKD *const xd = &pbi->mb;
 
-  int scaling_active;
+  int scaling_active, i;
   cm->last_frame_type = cm->frame_type;
+  if (vp9_rb_read_literal(rb, 2) != 0x2)
+      vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
+                         "Invalid frame marker");
+
+  cm->version = vp9_rb_read_bit(rb);
+  RESERVED;
+
+  if (vp9_rb_read_bit(rb)) {
+    // show an existing frame directly
+    int frame_to_show = cm->ref_frame_map[vp9_rb_read_literal(rb, 3)];
+    ref_cnt_fb(cm->fb_idx_ref_cnt, &cm->new_fb_idx, frame_to_show);
+    pbi->refresh_frame_flags = 0;
+    cm->filter_level = 0;
+    return 0;
+  }
   cm->frame_type = (FRAME_TYPE) vp9_rb_read_bit(rb);
-  cm->version = vp9_rb_read_literal(rb, 3);
   cm->show_frame = vp9_rb_read_bit(rb);
   scaling_active = vp9_rb_read_bit(rb);
-  cm->subsampling_x = vp9_rb_read_bit(rb);
-  cm->subsampling_y = vp9_rb_read_bit(rb);
 
   if (cm->frame_type == KEY_FRAME) {
     if (vp9_rb_read_literal(rb, 8) != SYNC_CODE_0 ||
         vp9_rb_read_literal(rb, 8) != SYNC_CODE_1 ||
         vp9_rb_read_literal(rb, 8) != SYNC_CODE_2) {
-        vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
-                           "Invalid frame sync code");
+      vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
+                         "Invalid frame sync code");
+    }
+    vp9_rb_read_literal(rb, 3);  // colorspace
+    if (cm->version == 1) {
+      cm->subsampling_x = vp9_rb_read_bit(rb);
+      cm->subsampling_y = vp9_rb_read_bit(rb);
+      vp9_rb_read_bit(rb);  // has extra plane
+    } else {
+      cm->subsampling_y = cm->subsampling_x = 1;
     }
   }
 
   setup_frame_size(pbi, scaling_active, rb);
 
-  if (!cm->show_frame) {
-    cm->intra_only = vp9_rb_read_bit(rb);
-  } else {
-    cm->intra_only = 0;
-  }
-
-  cm->frame_context_idx = vp9_rb_read_literal(rb, NUM_FRAME_CONTEXTS_LG2);
-  cm->clr_type = (YUV_TYPE)vp9_rb_read_bit(rb);
-
   cm->error_resilient_mode = vp9_rb_read_bit(rb);
   if (!cm->error_resilient_mode) {
     cm->reset_frame_context = vp9_rb_read_bit(rb);
@@ -945,8 +977,64 @@
     cm->frame_parallel_decoding_mode = 1;
   }
 
+  if (cm->frame_type == KEY_FRAME) {
+    vp9_setup_past_independence(cm, xd);
+
+    pbi->refresh_frame_flags = (1 << NUM_REF_FRAMES) - 1;
+
+    for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i)
+      cm->active_ref_idx[i] = cm->new_fb_idx;
+  } else {
+    if (cm->error_resilient_mode)
+      vp9_setup_past_independence(cm, xd);
+
+    pbi->refresh_frame_flags = vp9_rb_read_literal(rb, NUM_REF_FRAMES);
+
+    for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i) {
+      const int ref = vp9_rb_read_literal(rb, NUM_REF_FRAMES_LG2);
+      cm->active_ref_idx[i] = cm->ref_frame_map[ref];
+      vp9_setup_scale_factors(cm, i);
+    }
+
+    // Read the sign bias for each reference frame buffer.
+    cm->allow_comp_inter_inter = 0;
+    for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i) {
+      cm->ref_frame_sign_bias[i + 1] = vp9_rb_read_bit(rb);
+      cm->allow_comp_inter_inter |= i > 0 &&
+          cm->ref_frame_sign_bias[i + 1] != cm->ref_frame_sign_bias[1];
+    }
+    if (cm->allow_comp_inter_inter) {
+      // which one is always-on in comp inter-inter?
+      if (cm->ref_frame_sign_bias[LAST_FRAME] ==
+          cm->ref_frame_sign_bias[GOLDEN_FRAME]) {
+        cm->comp_fixed_ref = ALTREF_FRAME;
+        cm->comp_var_ref[0] = LAST_FRAME;
+        cm->comp_var_ref[1] = GOLDEN_FRAME;
+      } else if (cm->ref_frame_sign_bias[LAST_FRAME] ==
+                 cm->ref_frame_sign_bias[ALTREF_FRAME]) {
+        cm->comp_fixed_ref = GOLDEN_FRAME;
+        cm->comp_var_ref[0] = LAST_FRAME;
+        cm->comp_var_ref[1] = ALTREF_FRAME;
+      } else {
+        cm->comp_fixed_ref = LAST_FRAME;
+        cm->comp_var_ref[0] = GOLDEN_FRAME;
+        cm->comp_var_ref[1] = ALTREF_FRAME;
+      }
+    }
+
+    xd->allow_high_precision_mv = vp9_rb_read_bit(rb);
+    cm->mcomp_filter_type = read_interp_filter_type(rb);
+  }
+
+  cm->intra_only = cm->show_frame ? 0 : vp9_rb_read_bit(rb);
+  cm->frame_context_idx = vp9_rb_read_literal(rb, NUM_FRAME_CONTEXTS_LG2);
+  cm->clr_type = (YUV_TYPE)vp9_rb_read_bit(rb);
+
   setup_loopfilter(pbi, rb);
   setup_quantization(pbi, rb);
+  setup_segmentation(pbi, rb);
+
+  setup_tile_info(cm, rb);
 
   return vp9_rb_read_literal(rb, 16);
 }
@@ -956,7 +1044,7 @@
   vp9_reader header_bc, residual_bc;
   VP9_COMMON *const pc = &pbi->common;
   MACROBLOCKD *const xd = &pbi->mb;
-  YV12_BUFFER_CONFIG *new_fb = &pc->yv12_fb[pc->new_fb_idx];
+
   const uint8_t *data = pbi->source;
   const uint8_t *data_end = pbi->source + pbi->source_sz;
 
@@ -964,7 +1052,13 @@
                                     pc, error_handler };
   const size_t first_partition_size = read_uncompressed_header(pbi, &rb);
   const int keyframe = pc->frame_type == KEY_FRAME;
+  YV12_BUFFER_CONFIG *new_fb = &pc->yv12_fb[pc->new_fb_idx];
 
+  if (!first_partition_size) {
+    // showing a frame directly
+    *p_data_end = data + 1;
+    return 0;
+  }
   data += vp9_rb_bytes_read(&rb);
   xd->corrupted = 0;
   new_fb->corrupted = 0;
@@ -976,15 +1070,13 @@
 
   vp9_setup_version(pc);
   if (!read_is_valid(data, first_partition_size, data_end))
-      vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
-                         "Truncated packet or corrupt partition 0 length");
+    vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+                       "Truncated packet or corrupt partition 0 length");
 
-  init_frame(pbi);
-
-  // Reset the frame pointers to the current frame size
-  vp9_realloc_frame_buffer(new_fb, pc->width, pc->height,
-                           pc->subsampling_x, pc->subsampling_y,
-                           VP9BORDERINPIXELS);
+  xd->mode_info_context = pc->mi;
+  xd->prev_mode_info_context = pc->prev_mi;
+  xd->frame_type = pc->frame_type;
+  xd->mode_info_stride = pc->mode_info_stride;
 
   if (vp9_reader_init(&header_bc, data, first_partition_size))
     vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
@@ -992,67 +1084,15 @@
 
   mb_init_dequantizer(pc, &pbi->mb);  // MB level dequantizer setup
 
-  xd->lossless = pc->base_qindex == 0 &&
-                 pc->y_dc_delta_q == 0 &&
-                 pc->uv_dc_delta_q == 0 &&
-                 pc->uv_ac_delta_q == 0;
-  if (xd->lossless) {
-    xd->itxm_add          = vp9_idct_add_lossless_c;
-    xd->itxm_add_y_block  = vp9_idct_add_y_block_lossless_c;
-    xd->itxm_add_uv_block = vp9_idct_add_uv_block_lossless_c;
-  } else {
-    xd->itxm_add          = vp9_idct_add;
-    xd->itxm_add_y_block  = vp9_idct_add_y_block;
-    xd->itxm_add_uv_block = vp9_idct_add_uv_block;
-  }
-
-  // Determine if the golden frame or ARF buffer should be updated and how.
-  // For all non key frames the GF and ARF refresh flags and sign bias
-  // flags must be set explicitly.
-  if (keyframe) {
-    for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i)
-      pc->active_ref_idx[i] = pc->new_fb_idx;
-  } else {
-    // Should the GF or ARF be updated from the current frame
-    pbi->refresh_frame_flags = vp9_read_literal(&header_bc, NUM_REF_FRAMES);
-
-    // Select active reference frames and calculate scaling factors
-    for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i) {
-      const int ref = vp9_read_literal(&header_bc, NUM_REF_FRAMES_LG2);
-      pc->active_ref_idx[i] = pc->ref_frame_map[ref];
-      vp9_setup_scale_factors(pc, i);
-    }
-
-    // Read the sign bias for each reference frame buffer.
-    for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i)
-      pc->ref_frame_sign_bias[i + 1] = vp9_read_bit(&header_bc);
-
-    xd->allow_high_precision_mv = vp9_read_bit(&header_bc);
-    pc->mcomp_filter_type = read_mcomp_filter_type(&header_bc);
-
-    // To enable choice of different interpolation filters
+  if (!keyframe)
     vp9_setup_interp_filters(xd, pc->mcomp_filter_type, pc);
-  }
 
   pc->fc = pc->frame_contexts[pc->frame_context_idx];
 
-  setup_segmentation(pc, xd, &header_bc);
-
-  setup_pred_probs(pc, &header_bc);
+  update_frame_context(&pc->fc);
 
   setup_txfm_mode(pc, xd->lossless, &header_bc);
 
-  // Read inter mode probability context updates
-  if (!keyframe) {
-    int i, j;
-    for (i = 0; i < INTER_MODE_CONTEXTS; ++i)
-      for (j = 0; j < VP9_MVREFS - 1; ++j)
-        if (vp9_read(&header_bc, 252))
-          pc->fc.vp9_mode_contexts[i][j] = vp9_read_prob(&header_bc);
-  }
-
-  update_frame_context(&pc->fc);
-
   read_coef_probs(pbi, &header_bc);
 
   // Initialize xd pointers. Any reference should do for xd->pre, so use 0.
@@ -1075,7 +1115,7 @@
 
   vp9_decode_mode_mvs_init(pbi, &header_bc);
 
-  decode_tiles(pbi, data, first_partition_size, &header_bc, &residual_bc);
+  decode_tiles(pbi, data, first_partition_size, &residual_bc);
 
   pc->last_width = pc->width;
   pc->last_height = pc->height;
diff --git a/vp9/decoder/vp9_decodframe.h b/vp9/decoder/vp9_decodframe.h
index 00b6d67..66e951d 100644
--- a/vp9/decoder/vp9_decodframe.h
+++ b/vp9/decoder/vp9_decodframe.h
@@ -17,5 +17,6 @@
 
 void vp9_init_dequantizer(struct VP9Common *pc);
 int vp9_decode_frame(struct VP9Decompressor *cpi, const uint8_t **p_data_end);
+vp9_prob vp9_read_prob_diff_update(vp9_reader *r, int oldp);
 
 #endif  // VP9_DECODER_VP9_DECODFRAME_H_
diff --git a/vp9/decoder/vp9_detokenize.c b/vp9/decoder/vp9_detokenize.c
index b208072..d06c9b0 100644
--- a/vp9/decoder/vp9_detokenize.c
+++ b/vp9/decoder/vp9_detokenize.c
@@ -111,7 +111,7 @@
 
   vp9_prob *prob;
   vp9_coeff_count_model *coef_counts;
-  const int ref = xd->mode_info_context->mbmi.ref_frame != INTRA_FRAME;
+  const int ref = xd->mode_info_context->mbmi.ref_frame[0] != INTRA_FRAME;
   TX_TYPE tx_type = DCT_DCT;
   const int *scan, *nb;
   uint8_t token_cache[1024];
@@ -288,18 +288,14 @@
   if (c < seg_eob)
     coef_counts[type][ref][band][pt][DCT_EOB_MODEL_TOKEN]++;
 
-  for (pt = 0; pt < (1 << txfm_size); pt++) {
-    A[pt] = L[pt] = c > 0;
-  }
 
   return c;
 }
 
 static int get_eob(MACROBLOCKD* const xd, int segment_id, int eob_max) {
-  return vp9_get_segdata(xd, segment_id, SEG_LVL_SKIP) ? 0 : eob_max;
+  return vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP) ? 0 : eob_max;
 }
 
-
 struct decode_block_args {
   VP9D_COMP *pbi;
   MACROBLOCKD *xd;
@@ -314,6 +310,7 @@
   const int bw = b_width_log2(bsize);
 
   // find the maximum eob for this transform size, adjusted by segment
+  MACROBLOCKD *xd = arg->xd;
   const int segment_id = arg->xd->mode_info_context->mbmi.segment_id;
   const TX_SIZE ss_tx_size = ss_txfrm_size / 2;
   const int seg_eob = get_eob(arg->xd, segment_id, 16 << ss_txfrm_size);
@@ -322,14 +319,23 @@
   const int mod = bw - ss_tx_size - arg->xd->plane[plane].subsampling_x;
   const int aoff = (off & ((1 << mod) - 1)) << ss_tx_size;
   const int loff = (off >> mod) << ss_tx_size;
-
+  int pt;
+  ENTROPY_CONTEXT *A = arg->xd->plane[plane].above_context + aoff;
+  ENTROPY_CONTEXT *L = arg->xd->plane[plane].left_context + loff;
   const int eob = decode_coefs(arg->pbi, arg->xd, arg->r, block,
                                arg->xd->plane[plane].plane_type, seg_eob,
                                BLOCK_OFFSET(qcoeff_base, block, 16),
                                ss_tx_size, arg->xd->plane[plane].dequant,
-                               arg->xd->plane[plane].above_context + aoff,
-                               arg->xd->plane[plane].left_context + loff);
+                               A,
+                               L);
 
+  if (xd->mb_to_right_edge < 0 || xd->mb_to_bottom_edge < 0) {
+    set_contexts_on_border(xd, bsize, plane, ss_tx_size, eob, aoff, loff, A, L);
+  } else {
+    for (pt = 0; pt < (1 << ss_tx_size); pt++) {
+      A[pt] = L[pt] = eob > 0;
+    }
+  }
   arg->xd->plane[plane].eobs[block] = eob;
   arg->eobtotal[0] += eob;
 }
diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c
index 043ac6a..28e107b 100644
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -53,11 +53,6 @@
 
 static int update_bits[255];
 
-static INLINE void write_le16(uint8_t *p, int value) {
-  p[0] = value;
-  p[1] = value >> 8;
-}
-
 static INLINE void write_le32(uint8_t *p, int value) {
   p[0] = value;
   p[1] = value >> 8;
@@ -65,14 +60,7 @@
   p[3] = value >> 24;
 }
 
-void vp9_encode_unsigned_max(vp9_writer *br, int data, int max) {
-  assert(data <= max);
-  while (max) {
-    vp9_write_bit(br, data & 1);
-    data >>= 1;
-    max >>= 1;
-  }
-}
+
 
 int recenter_nonneg(int v, int m) {
   if (v > (m << 1))
@@ -93,6 +81,11 @@
   return cat;
 }
 
+void vp9_encode_unsigned_max(struct vp9_write_bit_buffer *wb,
+                             int data, int max) {
+  vp9_wb_write_literal(wb, data, get_unsigned_bits(max));
+}
+
 void encode_uniform(vp9_writer *w, int v, int n) {
   int l = get_unsigned_bits(n);
   int m;
@@ -203,151 +196,6 @@
   return update_bits[delp] * 256;
 }
 
-static void update_mode(
-  vp9_writer *w,
-  int n,
-  const struct vp9_token tok[/* n */],
-  vp9_tree tree,
-  vp9_prob Pnew               [/* n-1 */],
-  vp9_prob Pcur               [/* n-1 */],
-  unsigned int bct            [/* n-1 */] [2],
-  const unsigned int num_events[/* n */]
-) {
-  unsigned int new_b = 0, old_b = 0;
-  int i = 0;
-
-  vp9_tree_probs_from_distribution(tree, Pnew, bct, num_events, 0);
-  n--;
-
-  do {
-    new_b += cost_branch(bct[i], Pnew[i]);
-    old_b += cost_branch(bct[i], Pcur[i]);
-  } while (++i < n);
-
-  if (new_b + (n << 8) < old_b) {
-    int i = 0;
-
-    vp9_write_bit(w, 1);
-
-    do {
-      const vp9_prob p = Pnew[i];
-
-      vp9_write_literal(w, Pcur[i] = p ? p : 1, 8);
-    } while (++i < n);
-  } else
-    vp9_write_bit(w, 0);
-}
-
-static void update_mbintra_mode_probs(VP9_COMP* const cpi,
-                                      vp9_writer* const bc) {
-  VP9_COMMON *const cm = &cpi->common;
-
-  vp9_prob pnew[VP9_INTRA_MODES - 1];
-  unsigned int bct[VP9_INTRA_MODES - 1][2];
-
-  update_mode(bc, VP9_INTRA_MODES, vp9_intra_mode_encodings,
-              vp9_intra_mode_tree, pnew,
-              cm->fc.y_mode_prob, bct, (unsigned int *)cpi->y_mode_count);
-}
-
-void vp9_update_skip_probs(VP9_COMP *cpi) {
-  VP9_COMMON *const pc = &cpi->common;
-  int k;
-
-  for (k = 0; k < MBSKIP_CONTEXTS; ++k)
-    pc->mbskip_pred_probs[k] = get_binary_prob(cpi->skip_false_count[k],
-                                               cpi->skip_true_count[k]);
-}
-
-static void update_switchable_interp_probs(VP9_COMP *cpi,
-                                           vp9_writer* const bc) {
-  VP9_COMMON *const pc = &cpi->common;
-  unsigned int branch_ct[32][2];
-  int i, j;
-  for (j = 0; j <= VP9_SWITCHABLE_FILTERS; ++j) {
-    vp9_tree_probs_from_distribution(
-        vp9_switchable_interp_tree,
-        pc->fc.switchable_interp_prob[j], branch_ct,
-        cpi->switchable_interp_count[j], 0);
-    for (i = 0; i < VP9_SWITCHABLE_FILTERS - 1; ++i) {
-      if (pc->fc.switchable_interp_prob[j][i] < 1)
-        pc->fc.switchable_interp_prob[j][i] = 1;
-      vp9_write_prob(bc, pc->fc.switchable_interp_prob[j][i]);
-    }
-  }
-}
-
-// This function updates the reference frame prediction stats
-static void update_refpred_stats(VP9_COMP *cpi) {
-  VP9_COMMON *const cm = &cpi->common;
-  int i;
-  vp9_prob new_pred_probs[PREDICTION_PROBS];
-  int old_cost, new_cost;
-
-  // Set the prediction probability structures to defaults
-  if (cm->frame_type != KEY_FRAME) {
-    // From the prediction counts set the probabilities for each context
-    for (i = 0; i < PREDICTION_PROBS; i++) {
-      const int c0 = cpi->ref_pred_count[i][0];
-      const int c1 = cpi->ref_pred_count[i][1];
-
-      new_pred_probs[i] = get_binary_prob(c0, c1);
-
-      // Decide whether or not to update the reference frame probs.
-      // Returned costs are in 1/256 bit units.
-      old_cost = c0 * vp9_cost_zero(cm->ref_pred_probs[i]) +
-                 c1 * vp9_cost_one(cm->ref_pred_probs[i]);
-
-      new_cost = c0 * vp9_cost_zero(new_pred_probs[i]) +
-                 c1 * vp9_cost_one(new_pred_probs[i]);
-
-      // Cost saving must be >= 8 bits (2048 in these units)
-      if ((old_cost - new_cost) >= 2048) {
-        cpi->ref_pred_probs_update[i] = 1;
-        cm->ref_pred_probs[i] = new_pred_probs[i];
-      } else
-        cpi->ref_pred_probs_update[i] = 0;
-    }
-  }
-}
-
-// This function is called to update the mode probability context used to encode
-// inter modes. It assumes the branch counts table has already been populated
-// prior to the actual packing of the bitstream (in rd stage or dummy pack)
-//
-// The branch counts table is re-populated during the actual pack stage and in
-// the decoder to facilitate backwards update of the context.
-static void update_inter_mode_probs(VP9_COMMON *cm,
-    int mode_context[INTER_MODE_CONTEXTS][VP9_MVREFS - 1]) {
-  int i, j;
-  unsigned int (*mv_ref_ct)[VP9_MVREFS - 1][2] = cm->fc.mv_ref_ct;
-
-  vpx_memcpy(mode_context, cm->fc.vp9_mode_contexts,
-             sizeof(cm->fc.vp9_mode_contexts));
-
-  for (i = 0; i < INTER_MODE_CONTEXTS; i++) {
-    for (j = 0; j < VP9_MVREFS - 1; j++) {
-      int new_prob, old_cost, new_cost;
-
-      // Work out cost of coding branches with the old and optimal probability
-      old_cost = cost_branch256(mv_ref_ct[i][j], mode_context[i][j]);
-      new_prob = get_binary_prob(mv_ref_ct[i][j][0], mv_ref_ct[i][j][1]);
-      new_cost = cost_branch256(mv_ref_ct[i][j], new_prob);
-
-      // If cost saving is >= 14 bits then update the mode probability.
-      // This is the approximate net cost of updating one probability given
-      // that the no update case ismuch more common than the update case.
-      if (new_cost <= (old_cost - (14 << 8))) {
-        mode_context[i][j] = new_prob;
-      }
-    }
-  }
-}
-
-static void write_intra_mode(vp9_writer *bc, int m, const vp9_prob *p) {
-  write_token(bc, vp9_intra_mode_tree, p, vp9_intra_mode_encodings + m);
-}
-
 static int prob_update_savings(const unsigned int *ct,
                                const vp9_prob oldp, const vp9_prob newp,
                                const vp9_prob upd) {
@@ -424,6 +272,7 @@
   vp9_prob newp;
   int savings;
   newp = get_binary_prob(ct[0], ct[1]);
+  assert(newp >= 1);
   savings = prob_update_savings(ct, *oldp, newp, upd);
   if (savings > 0) {
     vp9_write(bc, 1, upd);
@@ -434,6 +283,107 @@
   }
 }
 
+static void vp9_cond_prob_diff_update(vp9_writer *bc, vp9_prob *oldp,
+                                      vp9_prob upd,
+                                      unsigned int *ct) {
+  vp9_prob newp;
+  int savings;
+  newp = get_binary_prob(ct[0], ct[1]);
+  assert(newp >= 1);
+  savings = prob_diff_update_savings_search(ct, *oldp, &newp, upd);
+  if (savings > 0) {
+    vp9_write(bc, 1, upd);
+    write_prob_diff_update(bc, newp, *oldp);
+    *oldp = newp;
+  } else {
+    vp9_write(bc, 0, upd);
+  }
+}
+
+static void update_mode(
+  vp9_writer *w,
+  int n,
+  const struct vp9_token tok[/* n */],
+  vp9_tree tree,
+  vp9_prob Pnew[/* n-1 */],
+  vp9_prob Pcur[/* n-1 */],
+  unsigned int bct[/* n-1 */] [2],
+  const unsigned int num_events[/* n */]
+) {
+  int i = 0;
+
+  vp9_tree_probs_from_distribution(tree, Pnew, bct, num_events, 0);
+  n--;
+
+  for (i = 0; i < n; ++i) {
+    vp9_cond_prob_diff_update(w, &Pcur[i], VP9_DEF_UPDATE_PROB, bct[i]);
+  }
+}
+
+static void update_mbintra_mode_probs(VP9_COMP* const cpi,
+                                      vp9_writer* const bc) {
+  VP9_COMMON *const cm = &cpi->common;
+  int j;
+  vp9_prob pnew[VP9_INTRA_MODES - 1];
+  unsigned int bct[VP9_INTRA_MODES - 1][2];
+
+  for (j = 0; j < BLOCK_SIZE_GROUPS; j++)
+    update_mode(bc, VP9_INTRA_MODES, vp9_intra_mode_encodings,
+                vp9_intra_mode_tree, pnew,
+                cm->fc.y_mode_prob[j], bct,
+                (unsigned int *)cpi->y_mode_count[j]);
+}
+
+void vp9_update_skip_probs(VP9_COMP *cpi) {
+  VP9_COMMON *const pc = &cpi->common;
+  int k;
+
+  for (k = 0; k < MBSKIP_CONTEXTS; ++k)
+    pc->mbskip_pred_probs[k] = get_binary_prob(cpi->skip_false_count[k],
+                                               cpi->skip_true_count[k]);
+}
+
+static void write_intra_mode(vp9_writer *bc, int m, const vp9_prob *p) {
+  write_token(bc, vp9_intra_mode_tree, p, vp9_intra_mode_encodings + m);
+}
+
+static void update_switchable_interp_probs(VP9_COMMON *const pc,
+                                           vp9_writer* const bc) {
+  unsigned int branch_ct[VP9_SWITCHABLE_FILTERS + 1]
+                        [VP9_SWITCHABLE_FILTERS - 1][2];
+  vp9_prob new_prob[VP9_SWITCHABLE_FILTERS + 1][VP9_SWITCHABLE_FILTERS - 1];
+  int i, j;
+  for (j = 0; j <= VP9_SWITCHABLE_FILTERS; ++j) {
+    vp9_tree_probs_from_distribution(
+        vp9_switchable_interp_tree,
+        new_prob[j], branch_ct[j],
+        pc->fc.switchable_interp_count[j], 0);
+  }
+  for (j = 0; j <= VP9_SWITCHABLE_FILTERS; ++j) {
+    for (i = 0; i < VP9_SWITCHABLE_FILTERS - 1; ++i) {
+      // vp9_cond_prob_update(bc, &pc->fc.switchable_interp_prob[j][i],
+      //                      VP9_DEF_UPDATE_PROB, branch_ct[j][i]);
+      vp9_cond_prob_diff_update(bc, &pc->fc.switchable_interp_prob[j][i],
+                                VP9_DEF_UPDATE_PROB, branch_ct[j][i]);
+    }
+  }
+}
+
+static void update_inter_mode_probs(VP9_COMMON *pc, vp9_writer* const bc) {
+  int i, j;
+
+  for (i = 0; i < INTER_MODE_CONTEXTS; i++) {
+    for (j = 0; j < VP9_INTER_MODES - 1; j++) {
+      vp9_cond_prob_diff_update(bc, &pc->fc.inter_mode_probs[i][j],
+                                VP9_DEF_UPDATE_PROB,
+                                pc->fc.inter_mode_counts[i][j]);
+      // vp9_cond_prob_update(
+      //     bc, &pc->fc.inter_mode_probs[i][j],
+      //     VP9_DEF_UPDATE_PROB, pc->fc.inter_mode_counts[i][j]);
+    }
+  }
+}
+
 static void pack_mb_tokens(vp9_writer* const bc,
                            TOKENEXTRA **tp,
                            const TOKENEXTRA *const stop) {
@@ -525,16 +475,15 @@
 }
 
 // This function encodes the reference frame
-static void encode_ref_frame(vp9_writer *const bc,
-                             VP9_COMMON *const cm,
-                             MACROBLOCKD *xd,
-                             int segment_id,
-                             MV_REFERENCE_FRAME rf) {
-  int seg_ref_active;
+static void encode_ref_frame(VP9_COMP *cpi, vp9_writer *bc) {
+  VP9_COMMON *const pc = &cpi->common;
+  MACROBLOCK *const x = &cpi->mb;
+  MACROBLOCKD *const xd = &x->e_mbd;
+  MB_MODE_INFO *mi = &xd->mode_info_context->mbmi;
+  const int segment_id = mi->segment_id;
+  int seg_ref_active = vp9_segfeature_active(xd, segment_id,
+                                             SEG_LVL_REF_FRAME);
   int seg_ref_count = 0;
-  seg_ref_active = vp9_segfeature_active(xd,
-                                         segment_id,
-                                         SEG_LVL_REF_FRAME);
 
   if (seg_ref_active) {
     seg_ref_count = vp9_check_segref(xd, segment_id, INTRA_FRAME) +
@@ -546,84 +495,35 @@
   // If segment level coding of this signal is disabled...
   // or the segment allows multiple reference frame options
   if (!seg_ref_active || (seg_ref_count > 1)) {
-    // Values used in prediction model coding
-    unsigned char prediction_flag;
-    vp9_prob pred_prob;
-    MV_REFERENCE_FRAME pred_rf;
-
-    // Get the context probability the prediction flag
-    pred_prob = vp9_get_pred_prob(cm, xd, PRED_REF);
-
-    // Get the predicted value.
-    pred_rf = vp9_get_pred_ref(cm, xd);
-
-    // Did the chosen reference frame match its predicted value.
-    prediction_flag =
-      (xd->mode_info_context->mbmi.ref_frame == pred_rf);
-
-    vp9_set_pred_flag(xd, PRED_REF, prediction_flag);
-    vp9_write(bc, prediction_flag, pred_prob);
-
-    // If not predicted correctly then code value explicitly
-    if (!prediction_flag) {
-      vp9_prob mod_refprobs[PREDICTION_PROBS];
-
-      vpx_memcpy(mod_refprobs,
-                 cm->mod_refprobs[pred_rf], sizeof(mod_refprobs));
-
-      // If segment coding enabled blank out options that cant occur by
-      // setting the branch probability to 0.
-      if (seg_ref_active) {
-        mod_refprobs[INTRA_FRAME] *=
-          vp9_check_segref(xd, segment_id, INTRA_FRAME);
-        mod_refprobs[LAST_FRAME] *=
-          vp9_check_segref(xd, segment_id, LAST_FRAME);
-        mod_refprobs[GOLDEN_FRAME] *=
-          (vp9_check_segref(xd, segment_id, GOLDEN_FRAME) *
-           vp9_check_segref(xd, segment_id, ALTREF_FRAME));
-      }
-
-      if (mod_refprobs[0]) {
-        vp9_write(bc, (rf != INTRA_FRAME), mod_refprobs[0]);
-      }
-
-      // Inter coded
-      if (rf != INTRA_FRAME) {
-        if (mod_refprobs[1]) {
-          vp9_write(bc, (rf != LAST_FRAME), mod_refprobs[1]);
-        }
-
-        if (rf != LAST_FRAME) {
-          if (mod_refprobs[2]) {
-            vp9_write(bc, (rf != GOLDEN_FRAME), mod_refprobs[2]);
-          }
-        }
-      }
+    // does the feature use compound prediction or not
+    // (if not specified at the frame/segment level)
+    if (pc->comp_pred_mode == HYBRID_PREDICTION) {
+      vp9_write(bc, mi->ref_frame[1] > INTRA_FRAME,
+                vp9_get_pred_prob(pc, xd, PRED_COMP_INTER_INTER));
+    } else {
+      assert((mi->ref_frame[1] <= INTRA_FRAME) ==
+                 (pc->comp_pred_mode == SINGLE_PREDICTION_ONLY));
     }
+
+    if (mi->ref_frame[1] > INTRA_FRAME) {
+      vp9_write(bc, mi->ref_frame[0] == GOLDEN_FRAME,
+                vp9_get_pred_prob(pc, xd, PRED_COMP_REF_P));
+    } else {
+      vp9_write(bc, mi->ref_frame[0] != LAST_FRAME,
+                vp9_get_pred_prob(pc, xd, PRED_SINGLE_REF_P1));
+      if (mi->ref_frame[0] != LAST_FRAME)
+        vp9_write(bc, mi->ref_frame[0] != GOLDEN_FRAME,
+                  vp9_get_pred_prob(pc, xd, PRED_SINGLE_REF_P2));
+    }
+  } else {
+    assert(mi->ref_frame[1] <= INTRA_FRAME);
+    assert(vp9_check_segref(xd, segment_id, mi->ref_frame[0]));
   }
 
   // if using the prediction mdoel we have nothing further to do because
   // the reference frame is fully coded by the segment
 }
 
-// Update the probabilities used to encode reference frame data
-static void update_ref_probs(VP9_COMP *const cpi) {
-  VP9_COMMON *const cm = &cpi->common;
-
-  const int *const rfct = cpi->count_mb_ref_frame_usage;
-  const int rf_intra = rfct[INTRA_FRAME];
-  const int rf_inter = rfct[LAST_FRAME] +
-                       rfct[GOLDEN_FRAME] + rfct[ALTREF_FRAME];
-
-  cm->prob_intra_coded = get_binary_prob(rf_intra, rf_inter);
-  cm->prob_last_coded = get_prob(rfct[LAST_FRAME], rf_inter);
-  cm->prob_gf_coded = get_binary_prob(rfct[GOLDEN_FRAME], rfct[ALTREF_FRAME]);
-
-  // Compute a modified set of probabilities to use when prediction of the
-  // reference frame fails
-  vp9_compute_mod_refprobs(cm);
-}
-
 static void pack_inter_mode_mvs(VP9_COMP *cpi, MODE_INFO *m,
                                 vp9_writer *bc, int mi_row, int mi_col) {
   VP9_COMMON *const pc = &cpi->common;
@@ -631,7 +531,7 @@
   MACROBLOCK *const x = &cpi->mb;
   MACROBLOCKD *const xd = &x->e_mbd;
   MB_MODE_INFO *const mi = &m->mbmi;
-  const MV_REFERENCE_FRAME rf = mi->ref_frame;
+  const MV_REFERENCE_FRAME rf = mi->ref_frame[0];
   const MB_PREDICTION_MODE mode = mi->mode;
   const int segment_id = mi->segment_id;
   int skip_coeff;
@@ -669,19 +569,18 @@
               vp9_get_pred_prob(pc, xd, PRED_MBSKIP));
   }
 
-  // Encode the reference frame.
-  encode_ref_frame(bc, pc, xd, segment_id, rf);
+  vp9_write(bc, rf != INTRA_FRAME, vp9_get_pred_prob(pc, xd, PRED_INTRA_INTER));
 
   if (mi->sb_type >= BLOCK_SIZE_SB8X8 && pc->txfm_mode == TX_MODE_SELECT &&
       !(rf != INTRA_FRAME &&
         (skip_coeff || vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP)))) {
     TX_SIZE sz = mi->txfm_size;
-    // FIXME(rbultje) code ternary symbol once all experiments are merged
-    vp9_write(bc, sz != TX_4X4, pc->prob_tx[0]);
+    int tx_probs_offset = get_tx_probs_offset(mi->sb_type);
+    vp9_write(bc, sz != TX_4X4, pc->fc.tx_probs[tx_probs_offset]);
     if (mi->sb_type >= BLOCK_SIZE_MB16X16 && sz != TX_4X4) {
-      vp9_write(bc, sz != TX_8X8, pc->prob_tx[1]);
+      vp9_write(bc, sz != TX_8X8, pc->fc.tx_probs[tx_probs_offset + 1]);
       if (mi->sb_type >= BLOCK_SIZE_SB32X32 && sz != TX_8X8)
-        vp9_write(bc, sz != TX_16X16, pc->prob_tx[2]);
+        vp9_write(bc, sz != TX_16X16, pc->fc.tx_probs[tx_probs_offset + 2]);
     }
   }
 
@@ -691,20 +590,26 @@
 #endif
 
     if (m->mbmi.sb_type >= BLOCK_SIZE_SB8X8) {
-      write_intra_mode(bc, mode, pc->fc.y_mode_prob);
+      const BLOCK_SIZE_TYPE bsize = xd->mode_info_context->mbmi.sb_type;
+      const int bwl = b_width_log2(bsize), bhl = b_height_log2(bsize);
+      const int bsl = MIN(bwl, bhl);
+      write_intra_mode(bc, mode, pc->fc.y_mode_prob[MIN(3, bsl)]);
     } else {
       int idx, idy;
       int bw = 1 << b_width_log2(mi->sb_type);
       int bh = 1 << b_height_log2(mi->sb_type);
       for (idy = 0; idy < 2; idy += bh)
-        for (idx = 0; idx < 2; idx += bw)
-          write_intra_mode(bc, m->bmi[idy * 2 + idx].as_mode.first,
-                           pc->fc.y_mode_prob);
+        for (idx = 0; idx < 2; idx += bw) {
+          MB_PREDICTION_MODE bm = m->bmi[idy * 2 + idx].as_mode.first;
+          write_intra_mode(bc, bm, pc->fc.y_mode_prob[0]);
+        }
     }
     write_intra_mode(bc, mi->uv_mode,
                      pc->fc.uv_mode_prob[mode]);
   } else {
-    vp9_prob mv_ref_p[VP9_MVREFS - 1];
+    vp9_prob mv_ref_p[VP9_INTER_MODES - 1];
+
+    encode_ref_frame(cpi, bc);
 
     vp9_mv_ref_probs(&cpi->common, mv_ref_p, mi->mb_mode_context[rf]);
 
@@ -730,13 +635,6 @@
       assert(mi->interp_filter == cpi->common.mcomp_filter_type);
     }
 
-    // does the feature use compound prediction or not
-    // (if not specified at the frame/segment level)
-    if (cpi->common.comp_pred_mode == HYBRID_PREDICTION) {
-      vp9_write(bc, mi->second_ref_frame > INTRA_FRAME,
-                vp9_get_pred_prob(pc, xd, PRED_COMP));
-    }
-
     if (xd->mode_info_context->mbmi.sb_type < BLOCK_SIZE_SB8X8) {
       int j;
       MB_PREDICTION_MODE blockmode;
@@ -758,7 +656,7 @@
             vp9_encode_mv(bc, &blockmv.as_mv, &mi->best_mv.as_mv,
                           nmvc, xd->allow_high_precision_mv);
 
-            if (mi->second_ref_frame > 0)
+            if (mi->ref_frame[1] > INTRA_FRAME)
               vp9_encode_mv(bc,
                             &cpi->mb.partition_info->bmi[j].second_mv.as_mv,
                             &mi->best_second_mv.as_mv,
@@ -778,7 +676,7 @@
                     &mi->mv[0].as_mv, &mi->best_mv.as_mv,
                     nmvc, xd->allow_high_precision_mv);
 
-      if (mi->second_ref_frame > 0)
+      if (mi->ref_frame[1] > INTRA_FRAME)
         vp9_encode_mv(bc,
                       &mi->mv[1].as_mv, &mi->best_second_mv.as_mv,
                       nmvc, xd->allow_high_precision_mv);
@@ -808,12 +706,12 @@
 
   if (m->mbmi.sb_type >= BLOCK_SIZE_SB8X8 && c->txfm_mode == TX_MODE_SELECT) {
     TX_SIZE sz = m->mbmi.txfm_size;
-    // FIXME(rbultje) code ternary symbol once all experiments are merged
-    vp9_write(bc, sz != TX_4X4, c->prob_tx[0]);
+    int tx_probs_offset = get_tx_probs_offset(m->mbmi.sb_type);
+    vp9_write(bc, sz != TX_4X4, c->fc.tx_probs[tx_probs_offset]);
     if (m->mbmi.sb_type >= BLOCK_SIZE_MB16X16 && sz != TX_4X4) {
-      vp9_write(bc, sz != TX_8X8, c->prob_tx[1]);
+      vp9_write(bc, sz != TX_8X8, c->fc.tx_probs[tx_probs_offset + 1]);
       if (m->mbmi.sb_type >= BLOCK_SIZE_SB32X32 && sz != TX_8X8)
-        vp9_write(bc, sz != TX_16X16, c->prob_tx[2]);
+        vp9_write(bc, sz != TX_16X16, c->fc.tx_probs[tx_probs_offset + 2]);
     }
   }
 
@@ -915,7 +813,8 @@
     xd->above_seg_context = cm->above_seg_context + mi_col;
     pl = partition_plane_context(xd, bsize);
     // encode the partition information
-    write_token(bc, vp9_partition_tree, cm->fc.partition_prob[pl],
+    write_token(bc, vp9_partition_tree,
+                cm->fc.partition_prob[cm->frame_type][pl],
                 vp9_partition_encodings + partition);
   }
 
@@ -1165,6 +1064,8 @@
 }
 
 static void update_coef_probs(VP9_COMP* const cpi, vp9_writer* const bc) {
+  const TXFM_MODE txfm_mode = cpi->common.txfm_mode;
+
   vp9_clear_system_state();
 
   // Build the cofficient contexts based on counts collected in encode loop
@@ -1172,37 +1073,15 @@
 
   update_coef_probs_common(bc, cpi, TX_4X4);
 
-  /* do not do this if not even allowed */
-  if (cpi->common.txfm_mode != ONLY_4X4) {
+  // do not do this if not even allowed
+  if (txfm_mode > ONLY_4X4)
     update_coef_probs_common(bc, cpi, TX_8X8);
-  }
 
-  if (cpi->common.txfm_mode > ALLOW_8X8) {
+  if (txfm_mode > ALLOW_8X8)
     update_coef_probs_common(bc, cpi, TX_16X16);
-  }
 
-  if (cpi->common.txfm_mode > ALLOW_16X16) {
+  if (txfm_mode > ALLOW_16X16)
     update_coef_probs_common(bc, cpi, TX_32X32);
-  }
-}
-
-static void segment_reference_frames(VP9_COMP *cpi) {
-  VP9_COMMON *oci = &cpi->common;
-  MODE_INFO *mi = oci->mi;
-  int ref[MAX_MB_SEGMENTS] = {0};
-  int i, j;
-  int mb_index = 0;
-  MACROBLOCKD *const xd = &cpi->mb.e_mbd;
-
-  for (i = 0; i < oci->mb_rows; i++) {
-    for (j = 0; j < oci->mb_cols; j++, mb_index++)
-      ref[mi[mb_index].mbmi.segment_id] |= (1 << mi[mb_index].mbmi.ref_frame);
-    mb_index++;
-  }
-  for (i = 0; i < MAX_MB_SEGMENTS; i++) {
-    vp9_enable_segfeature(xd, i, SEG_LVL_REF_FRAME);
-    vp9_set_segdata(xd, i, SEG_LVL_REF_FRAME, ref[i]);
-  }
 }
 
 static void encode_loopfilter(VP9_COMMON *pc, MACROBLOCKD *xd,
@@ -1275,73 +1154,62 @@
 }
 
 
-static void encode_segmentation(VP9_COMP *cpi, vp9_writer *w) {
+static void encode_segmentation(VP9_COMP *cpi,
+                               struct vp9_write_bit_buffer *wb) {
   int i, j;
-  VP9_COMMON *const pc = &cpi->common;
+  VP9_COMMON *const cm = &cpi->common;
   MACROBLOCKD *const xd = &cpi->mb.e_mbd;
 
-  vp9_write_bit(w, xd->segmentation_enabled);
+  vp9_wb_write_bit(wb, xd->segmentation_enabled);
   if (!xd->segmentation_enabled)
     return;
 
   // Segmentation map
-  vp9_write_bit(w, xd->update_mb_segmentation_map);
+  vp9_wb_write_bit(wb, xd->update_mb_segmentation_map);
   if (xd->update_mb_segmentation_map) {
     // Select the coding strategy (temporal or spatial)
     vp9_choose_segmap_coding_method(cpi);
     // Write out probabilities used to decode unpredicted  macro-block segments
     for (i = 0; i < MB_SEG_TREE_PROBS; i++) {
       const int prob = xd->mb_segment_tree_probs[i];
-      if (prob != MAX_PROB) {
-        vp9_write_bit(w, 1);
-        vp9_write_prob(w, prob);
-      } else {
-        vp9_write_bit(w, 0);
-      }
+      const int update = prob != MAX_PROB;
+      vp9_wb_write_bit(wb, update);
+      if (update)
+        vp9_wb_write_literal(wb, prob, 8);
     }
 
     // Write out the chosen coding method.
-    vp9_write_bit(w, pc->temporal_update);
-    if (pc->temporal_update) {
+    vp9_wb_write_bit(wb, cm->temporal_update);
+    if (cm->temporal_update) {
       for (i = 0; i < PREDICTION_PROBS; i++) {
-        const int prob = pc->segment_pred_probs[i];
-        if (prob != MAX_PROB) {
-          vp9_write_bit(w, 1);
-          vp9_write_prob(w, prob);
-        } else {
-          vp9_write_bit(w, 0);
-        }
+        const int prob = cm->segment_pred_probs[i];
+        const int update = prob != MAX_PROB;
+        vp9_wb_write_bit(wb, update);
+        if (update)
+          vp9_wb_write_literal(wb, prob, 8);
       }
     }
   }
 
   // Segmentation data
-  vp9_write_bit(w, xd->update_mb_segmentation_data);
-  // segment_reference_frames(cpi);
+  vp9_wb_write_bit(wb, xd->update_mb_segmentation_data);
   if (xd->update_mb_segmentation_data) {
-    vp9_write_bit(w, xd->mb_segment_abs_delta);
+    vp9_wb_write_bit(wb, xd->mb_segment_abs_delta);
 
     for (i = 0; i < MAX_MB_SEGMENTS; i++) {
       for (j = 0; j < SEG_LVL_MAX; j++) {
-        const int data = vp9_get_segdata(xd, i, j);
-        const int data_max = vp9_seg_feature_data_max(j);
-
-        if (vp9_segfeature_active(xd, i, j)) {
-          vp9_write_bit(w, 1);
+        const int active = vp9_segfeature_active(xd, i, j);
+        vp9_wb_write_bit(wb, active);
+        if (active) {
+          const int data = vp9_get_segdata(xd, i, j);
+          const int data_max = vp9_seg_feature_data_max(j);
 
           if (vp9_is_segfeature_signed(j)) {
-            if (data < 0) {
-              vp9_encode_unsigned_max(w, -data, data_max);
-              vp9_write_bit(w, 1);
-            } else {
-              vp9_encode_unsigned_max(w, data, data_max);
-              vp9_write_bit(w, 0);
-            }
+            vp9_encode_unsigned_max(wb, abs(data), data_max);
+            vp9_wb_write_bit(wb, data < 0);
           } else {
-            vp9_encode_unsigned_max(w, data, data_max);
+            vp9_encode_unsigned_max(wb, data, data_max);
           }
-        } else {
-          vp9_write_bit(w, 0);
         }
       }
     }
@@ -1349,7 +1217,7 @@
 }
 
 
-static void encode_txfm(VP9_COMP *cpi, vp9_writer *w) {
+static void encode_txfm_probs(VP9_COMP *cpi, vp9_writer *w) {
   VP9_COMMON *const cm = &cpi->common;
 
   // Mode
@@ -1359,38 +1227,72 @@
 
   // Probabilities
   if (cm->txfm_mode == TX_MODE_SELECT) {
-    cm->prob_tx[0] = get_prob(cpi->txfm_count_32x32p[TX_4X4] +
-                              cpi->txfm_count_16x16p[TX_4X4] +
-                              cpi->txfm_count_8x8p[TX_4X4],
-                              cpi->txfm_count_32x32p[TX_4X4] +
-                              cpi->txfm_count_32x32p[TX_8X8] +
-                              cpi->txfm_count_32x32p[TX_16X16] +
-                              cpi->txfm_count_32x32p[TX_32X32] +
-                              cpi->txfm_count_16x16p[TX_4X4] +
-                              cpi->txfm_count_16x16p[TX_8X8] +
-                              cpi->txfm_count_16x16p[TX_16X16] +
-                              cpi->txfm_count_8x8p[TX_4X4] +
-                              cpi->txfm_count_8x8p[TX_8X8]);
-    cm->prob_tx[1] = get_prob(cpi->txfm_count_32x32p[TX_8X8] +
-                              cpi->txfm_count_16x16p[TX_8X8],
-                              cpi->txfm_count_32x32p[TX_8X8] +
-                              cpi->txfm_count_32x32p[TX_16X16] +
-                              cpi->txfm_count_32x32p[TX_32X32] +
-                              cpi->txfm_count_16x16p[TX_8X8] +
-                              cpi->txfm_count_16x16p[TX_16X16]);
-    cm->prob_tx[2] = get_prob(cpi->txfm_count_32x32p[TX_16X16],
-                              cpi->txfm_count_32x32p[TX_16X16] +
-                              cpi->txfm_count_32x32p[TX_32X32]);
-    vp9_write_prob(w, cm->prob_tx[0]);
-    vp9_write_prob(w, cm->prob_tx[1]);
-    vp9_write_prob(w, cm->prob_tx[2]);
+    int i;
+    unsigned int ct[TX_SIZE_PROBS][2];
+    tx_counts_to_branch_counts(cm->fc.tx_count_32x32p,
+                               cm->fc.tx_count_16x16p,
+                               cm->fc.tx_count_8x8p, ct);
+
+    for (i = 0; i < TX_SIZE_PROBS; i++) {
+      vp9_cond_prob_diff_update(w, &cm->fc.tx_probs[i],
+                                VP9_DEF_UPDATE_PROB, ct[i]);
+    }
   } else {
-    cm->prob_tx[0] = 128;
-    cm->prob_tx[1] = 128;
-    cm->prob_tx[2] = 128;
+    vpx_memcpy(cm->fc.tx_probs, vp9_default_tx_probs,
+               sizeof(vp9_default_tx_probs));
   }
 }
 
+static void write_interp_filter_type(INTERPOLATIONFILTERTYPE type,
+                                     struct vp9_write_bit_buffer *wb) {
+  vp9_wb_write_bit(wb, type == SWITCHABLE);
+  if (type != SWITCHABLE)
+    vp9_wb_write_literal(wb, type, 2);
+}
+
+static void fix_mcomp_filter_type(VP9_COMP *cpi) {
+  VP9_COMMON *const cm = &cpi->common;
+
+  if (cm->mcomp_filter_type == SWITCHABLE) {
+    // Check to see if only one of the filters is actually used
+    int count[VP9_SWITCHABLE_FILTERS];
+    int i, j, c = 0;
+    for (i = 0; i < VP9_SWITCHABLE_FILTERS; ++i) {
+      count[i] = 0;
+      for (j = 0; j <= VP9_SWITCHABLE_FILTERS; ++j)
+        count[i] += cm->fc.switchable_interp_count[j][i];
+      c += (count[i] > 0);
+    }
+    if (c == 1) {
+      // Only one filter is used. So set the filter at frame level
+      for (i = 0; i < VP9_SWITCHABLE_FILTERS; ++i) {
+        if (count[i]) {
+          cm->mcomp_filter_type = vp9_switchable_interp[i];
+          break;
+        }
+      }
+    }
+  }
+}
+
+static void write_tile_info(VP9_COMMON *cm, struct vp9_write_bit_buffer *wb) {
+  int min_log2_tiles, delta_log2_tiles, n_tile_bits, n;
+  vp9_get_tile_n_bits(cm, &min_log2_tiles, &delta_log2_tiles);
+  n_tile_bits = cm->log2_tile_columns - min_log2_tiles;
+  for (n = 0; n < delta_log2_tiles; n++) {
+    if (n_tile_bits--) {
+      vp9_wb_write_bit(wb, 1);
+    } else {
+      vp9_wb_write_bit(wb, 0);
+      break;
+    }
+  }
+
+  vp9_wb_write_bit(wb, cm->log2_tile_rows != 0);
+  if (cm->log2_tile_rows != 0)
+    vp9_wb_write_bit(wb, cm->log2_tile_rows != 1);
+}
+
 void write_uncompressed_header(VP9_COMP *cpi,
                                struct vp9_write_bit_buffer *wb) {
   VP9_COMMON *const cm = &cpi->common;
@@ -1399,17 +1301,37 @@
   const int scaling_active = cm->width != cm->display_width ||
                              cm->height != cm->display_height;
 
+  // frame marker bits
+  vp9_wb_write_bit(wb, 1);
+  vp9_wb_write_bit(wb, 0);
+
+  // bitstream version.
+  // 00 - profile 0. 4:2:0 only
+  // 10 - profile 1. adds 4:4:4, 4:2:2, alpha
+  vp9_wb_write_bit(wb, cm->version);
+  vp9_wb_write_bit(wb, 0);
+
+  vp9_wb_write_bit(wb, 0);
   vp9_wb_write_bit(wb, cm->frame_type);
-  vp9_wb_write_literal(wb, cm->version, 3);
   vp9_wb_write_bit(wb, cm->show_frame);
   vp9_wb_write_bit(wb, scaling_active);
-  vp9_wb_write_bit(wb, cm->subsampling_x);
-  vp9_wb_write_bit(wb, cm->subsampling_y);
 
   if (cm->frame_type == KEY_FRAME) {
     vp9_wb_write_literal(wb, SYNC_CODE_0, 8);
     vp9_wb_write_literal(wb, SYNC_CODE_1, 8);
     vp9_wb_write_literal(wb, SYNC_CODE_2, 8);
+    // colorspaces
+    // 000 - Unknown
+    // 001 - BT.601
+    // 010 - BT.709
+    // 011 - xvYCC
+    // 1xx - Reserved
+    vp9_wb_write_literal(wb, 0, 3);
+    if (cm->version == 1) {
+      vp9_wb_write_bit(wb, cm->subsampling_x);
+      vp9_wb_write_bit(wb, cm->subsampling_y);
+      vp9_wb_write_bit(wb, 0);  // has extra plane
+    }
   }
 
   if (scaling_active) {
@@ -1420,13 +1342,6 @@
   vp9_wb_write_literal(wb, cm->width, 16);
   vp9_wb_write_literal(wb, cm->height, 16);
 
-  if (!cm->show_frame) {
-      vp9_wb_write_bit(wb, cm->intra_only);
-  }
-
-  vp9_wb_write_literal(wb, cm->frame_context_idx, NUM_FRAME_CONTEXTS_LG2);
-  vp9_wb_write_bit(wb, cm->clr_type);
-
   vp9_wb_write_bit(wb, cm->error_resilient_mode);
   if (!cm->error_resilient_mode) {
     vp9_wb_write_bit(wb, cm->reset_frame_context);
@@ -1434,8 +1349,71 @@
     vp9_wb_write_bit(wb, cm->frame_parallel_decoding_mode);
   }
 
+  // When there is a key frame all reference buffers are updated using the new key frame
+  if (cm->frame_type != KEY_FRAME) {
+    int refresh_mask, i;
+
+    // Should the GF or ARF be updated using the transmitted frame or buffer
+#if CONFIG_MULTIPLE_ARF
+    if (!cpi->multi_arf_enabled && cpi->refresh_golden_frame &&
+        !cpi->refresh_alt_ref_frame) {
+#else
+    if (cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame) {
+#endif
+      // Preserve the previously existing golden frame and update the frame in
+      // the alt ref slot instead. This is highly specific to the use of
+      // alt-ref as a forward reference, and this needs to be generalized as
+      // other uses are implemented (like RTC/temporal scaling)
+      //
+      // gld_fb_idx and alt_fb_idx need to be swapped for future frames, but
+      // that happens in vp9_onyx_if.c:update_reference_frames() so that it can
+      // be done outside of the recode loop.
+      refresh_mask = (cpi->refresh_last_frame << cpi->lst_fb_idx) |
+                     (cpi->refresh_golden_frame << cpi->alt_fb_idx);
+    } else {
+      int arf_idx = cpi->alt_fb_idx;
+#if CONFIG_MULTIPLE_ARF
+      // Determine which ARF buffer to use to encode this ARF frame.
+      if (cpi->multi_arf_enabled) {
+        int sn = cpi->sequence_number;
+        arf_idx = (cpi->frame_coding_order[sn] < 0) ?
+            cpi->arf_buffer_idx[sn + 1] :
+            cpi->arf_buffer_idx[sn];
+      }
+#endif
+      refresh_mask = (cpi->refresh_last_frame << cpi->lst_fb_idx) |
+                     (cpi->refresh_golden_frame << cpi->gld_fb_idx) |
+                     (cpi->refresh_alt_ref_frame << arf_idx);
+    }
+
+    vp9_wb_write_literal(wb, refresh_mask, NUM_REF_FRAMES);
+    vp9_wb_write_literal(wb, cpi->lst_fb_idx, NUM_REF_FRAMES_LG2);
+    vp9_wb_write_literal(wb, cpi->gld_fb_idx, NUM_REF_FRAMES_LG2);
+    vp9_wb_write_literal(wb, cpi->alt_fb_idx, NUM_REF_FRAMES_LG2);
+
+    // Indicate the sign bias for each reference frame buffer.
+    for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i)
+      vp9_wb_write_bit(wb, cm->ref_frame_sign_bias[LAST_FRAME + i]);
+
+    // Signal whether to allow high MV precision
+    vp9_wb_write_bit(wb, xd->allow_high_precision_mv);
+
+    // Signal the type of subpel filter to use
+    fix_mcomp_filter_type(cpi);
+    write_interp_filter_type(cm->mcomp_filter_type, wb);
+  }
+
+  if (!cm->show_frame)
+    vp9_wb_write_bit(wb, cm->intra_only);
+
+  vp9_wb_write_literal(wb, cm->frame_context_idx, NUM_FRAME_CONTEXTS_LG2);
+  vp9_wb_write_bit(wb, cm->clr_type);
+
   encode_loopfilter(cm, xd, wb);
   encode_quantization(cm, wb);
+  encode_segmentation(cpi, wb);
+
+  write_tile_info(cm, wb);
 }
 
 void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, unsigned long *size) {
@@ -1459,82 +1437,6 @@
 
   vp9_start_encode(&header_bc, cx_data);
 
-  // When there is a key frame all reference buffers are updated using the new key frame
-  if (pc->frame_type != KEY_FRAME) {
-    int refresh_mask;
-
-    // Should the GF or ARF be updated using the transmitted frame or buffer
-#if CONFIG_MULTIPLE_ARF
-    if (!cpi->multi_arf_enabled && cpi->refresh_golden_frame &&
-        !cpi->refresh_alt_ref_frame) {
-#else
-      if (cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame) {
-#endif
-      /* Preserve the previously existing golden frame and update the frame in
-       * the alt ref slot instead. This is highly specific to the use of
-       * alt-ref as a forward reference, and this needs to be generalized as
-       * other uses are implemented (like RTC/temporal scaling)
-       *
-       * gld_fb_idx and alt_fb_idx need to be swapped for future frames, but
-       * that happens in vp9_onyx_if.c:update_reference_frames() so that it can
-       * be done outside of the recode loop.
-       */
-      refresh_mask = (cpi->refresh_last_frame << cpi->lst_fb_idx) |
-                     (cpi->refresh_golden_frame << cpi->alt_fb_idx);
-    } else {
-      int arf_idx = cpi->alt_fb_idx;
-#if CONFIG_MULTIPLE_ARF
-      // Determine which ARF buffer to use to encode this ARF frame.
-      if (cpi->multi_arf_enabled) {
-        int sn = cpi->sequence_number;
-        arf_idx = (cpi->frame_coding_order[sn] < 0) ?
-            cpi->arf_buffer_idx[sn + 1] :
-            cpi->arf_buffer_idx[sn];
-      }
-#endif
-      refresh_mask = (cpi->refresh_last_frame << cpi->lst_fb_idx) |
-                     (cpi->refresh_golden_frame << cpi->gld_fb_idx) |
-                     (cpi->refresh_alt_ref_frame << arf_idx);
-    }
-
-    vp9_write_literal(&header_bc, refresh_mask, NUM_REF_FRAMES);
-    vp9_write_literal(&header_bc, cpi->lst_fb_idx, NUM_REF_FRAMES_LG2);
-    vp9_write_literal(&header_bc, cpi->gld_fb_idx, NUM_REF_FRAMES_LG2);
-    vp9_write_literal(&header_bc, cpi->alt_fb_idx, NUM_REF_FRAMES_LG2);
-
-    // Indicate the sign bias for each reference frame buffer.
-    for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i) {
-      vp9_write_bit(&header_bc, pc->ref_frame_sign_bias[LAST_FRAME + i]);
-    }
-
-    // Signal whether to allow high MV precision
-    vp9_write_bit(&header_bc, (xd->allow_high_precision_mv) ? 1 : 0);
-    if (pc->mcomp_filter_type == SWITCHABLE) {
-      /* Check to see if only one of the filters is actually used */
-      int count[VP9_SWITCHABLE_FILTERS];
-      int i, j, c = 0;
-      for (i = 0; i < VP9_SWITCHABLE_FILTERS; ++i) {
-        count[i] = 0;
-        for (j = 0; j <= VP9_SWITCHABLE_FILTERS; ++j)
-          count[i] += cpi->switchable_interp_count[j][i];
-        c += (count[i] > 0);
-      }
-      if (c == 1) {
-        /* Only one filter is used. So set the filter at frame level */
-        for (i = 0; i < VP9_SWITCHABLE_FILTERS; ++i) {
-          if (count[i]) {
-            pc->mcomp_filter_type = vp9_switchable_interp[i];
-            break;
-          }
-        }
-      }
-    }
-    // Signal the type of subpel filter to use
-    vp9_write_bit(&header_bc, (pc->mcomp_filter_type == SWITCHABLE));
-    if (pc->mcomp_filter_type != SWITCHABLE)
-      vp9_write_literal(&header_bc, (pc->mcomp_filter_type), 2);
-  }
-
 #ifdef ENTROPY_STATS
   if (pc->frame_type == INTER_FRAME)
     active_section = 0;
@@ -1542,65 +1444,28 @@
     active_section = 7;
 #endif
 
-  encode_segmentation(cpi, &header_bc);
-
-  // Encode the common prediction model status flag probability updates for
-  // the reference frame
-  update_refpred_stats(cpi);
-  if (pc->frame_type != KEY_FRAME) {
-    for (i = 0; i < PREDICTION_PROBS; i++) {
-      if (cpi->ref_pred_probs_update[i]) {
-        vp9_write_bit(&header_bc, 1);
-        vp9_write_prob(&header_bc, pc->ref_pred_probs[i]);
-      } else {
-        vp9_write_bit(&header_bc, 0);
-      }
-    }
-  }
-
-  if (xd->lossless)
-    pc->txfm_mode = ONLY_4X4;
-  else
-    encode_txfm(cpi, &header_bc);
-
-  // If appropriate update the inter mode probability context and code the
-  // changes in the bitstream.
-  if (pc->frame_type != KEY_FRAME) {
-    int i, j;
-    int new_context[INTER_MODE_CONTEXTS][VP9_MVREFS - 1];
-    if (!cpi->dummy_packing) {
-      update_inter_mode_probs(pc, new_context);
-    } else {
-      // In dummy pack assume context unchanged.
-      vpx_memcpy(new_context, pc->fc.vp9_mode_contexts,
-                 sizeof(pc->fc.vp9_mode_contexts));
-    }
-
-    for (i = 0; i < INTER_MODE_CONTEXTS; i++) {
-      for (j = 0; j < VP9_MVREFS - 1; j++) {
-        if (new_context[i][j] != pc->fc.vp9_mode_contexts[i][j]) {
-          vp9_write(&header_bc, 1, 252);
-          vp9_write_prob(&header_bc, new_context[i][j]);
-
-          // Only update the persistent copy if this is the "real pack"
-          if (!cpi->dummy_packing) {
-            pc->fc.vp9_mode_contexts[i][j] = new_context[i][j];
-          }
-        } else {
-          vp9_write(&header_bc, 0, 252);
-        }
-      }
-    }
-  }
-
   vp9_clear_system_state();  // __asm emms;
 
-  vp9_copy(cpi->common.fc.pre_coef_probs, cpi->common.fc.coef_probs);
-  vp9_copy(cpi->common.fc.pre_y_mode_prob, cpi->common.fc.y_mode_prob);
-  vp9_copy(cpi->common.fc.pre_uv_mode_prob, cpi->common.fc.uv_mode_prob);
-  vp9_copy(cpi->common.fc.pre_partition_prob, cpi->common.fc.partition_prob);
+  vp9_copy(pc->fc.pre_coef_probs, pc->fc.coef_probs);
+  vp9_copy(pc->fc.pre_y_mode_prob, pc->fc.y_mode_prob);
+  vp9_copy(pc->fc.pre_uv_mode_prob, pc->fc.uv_mode_prob);
+  vp9_copy(cpi->common.fc.pre_partition_prob,
+           cpi->common.fc.partition_prob[INTER_FRAME]);
+  pc->fc.pre_nmvc = pc->fc.nmvc;
+  vp9_copy(pc->fc.pre_switchable_interp_prob, pc->fc.switchable_interp_prob);
+  vp9_copy(pc->fc.pre_inter_mode_probs, pc->fc.inter_mode_probs);
+  vp9_copy(pc->fc.pre_intra_inter_prob, pc->fc.intra_inter_prob);
+  vp9_copy(pc->fc.pre_comp_inter_prob, pc->fc.comp_inter_prob);
+  vp9_copy(pc->fc.pre_comp_ref_prob, pc->fc.comp_ref_prob);
+  vp9_copy(pc->fc.pre_single_ref_prob, pc->fc.single_ref_prob);
   cpi->common.fc.pre_nmvc = cpi->common.fc.nmvc;
-  vp9_zero(cpi->common.fc.mv_ref_ct);
+  vp9_copy(cpi->common.fc.pre_tx_probs, cpi->common.fc.tx_probs);
+
+  if (xd->lossless) {
+    pc->txfm_mode = ONLY_4X4;
+  } else {
+    encode_txfm_probs(cpi, &header_bc);
+  }
 
   update_coef_probs(cpi, &header_bc);
 
@@ -1609,26 +1474,25 @@
 #endif
 
   vp9_update_skip_probs(cpi);
-  for (i = 0; i < MBSKIP_CONTEXTS; ++i) {
+  for (i = 0; i < MBSKIP_CONTEXTS; ++i)
     vp9_write_prob(&header_bc, pc->mbskip_pred_probs[i]);
-  }
 
   if (pc->frame_type != KEY_FRAME) {
-    // Update the probabilities used to encode reference frame data
-    update_ref_probs(cpi);
-
 #ifdef ENTROPY_STATS
     active_section = 1;
 #endif
 
+    update_inter_mode_probs(pc, &header_bc);
+    vp9_zero(cpi->common.fc.inter_mode_counts);
+
     if (pc->mcomp_filter_type == SWITCHABLE)
-      update_switchable_interp_probs(cpi, &header_bc);
+      update_switchable_interp_probs(pc, &header_bc);
 
-    vp9_write_prob(&header_bc, pc->prob_intra_coded);
-    vp9_write_prob(&header_bc, pc->prob_last_coded);
-    vp9_write_prob(&header_bc, pc->prob_gf_coded);
+    for (i = 0; i < INTRA_INTER_CONTEXTS; i++)
+      vp9_cond_prob_diff_update(&header_bc, &pc->fc.intra_inter_prob[i],
+                                VP9_DEF_UPDATE_PROB, cpi->intra_inter_count[i]);
 
-    {
+    if (pc->allow_comp_inter_inter) {
       const int comp_pred_mode = cpi->common.comp_pred_mode;
       const int use_compound_pred = (comp_pred_mode != SINGLE_PREDICTION_ONLY);
       const int use_hybrid_pred = (comp_pred_mode == HYBRID_PREDICTION);
@@ -1637,45 +1501,46 @@
       if (use_compound_pred) {
         vp9_write_bit(&header_bc, use_hybrid_pred);
         if (use_hybrid_pred) {
-          for (i = 0; i < COMP_PRED_CONTEXTS; i++) {
-            pc->prob_comppred[i] = get_binary_prob(cpi->single_pred_count[i],
-                                                   cpi->comp_pred_count[i]);
-            vp9_write_prob(&header_bc, pc->prob_comppred[i]);
-          }
+          for (i = 0; i < COMP_INTER_CONTEXTS; i++)
+            vp9_cond_prob_diff_update(&header_bc, &pc->fc.comp_inter_prob[i],
+                                      VP9_DEF_UPDATE_PROB,
+                                      cpi->comp_inter_count[i]);
         }
       }
     }
+
+    if (pc->comp_pred_mode != COMP_PREDICTION_ONLY) {
+      for (i = 0; i < REF_CONTEXTS; i++) {
+        vp9_cond_prob_diff_update(&header_bc, &pc->fc.single_ref_prob[i][0],
+                                  VP9_DEF_UPDATE_PROB,
+                                  cpi->single_ref_count[i][0]);
+        vp9_cond_prob_diff_update(&header_bc, &pc->fc.single_ref_prob[i][1],
+                                  VP9_DEF_UPDATE_PROB,
+                                  cpi->single_ref_count[i][1]);
+      }
+    }
+
+    if (pc->comp_pred_mode != SINGLE_PREDICTION_ONLY) {
+      for (i = 0; i < REF_CONTEXTS; i++)
+        vp9_cond_prob_diff_update(&header_bc, &pc->fc.comp_ref_prob[i],
+                                  VP9_DEF_UPDATE_PROB,
+                                  cpi->comp_ref_count[i]);
+    }
+
     update_mbintra_mode_probs(cpi, &header_bc);
 
     for (i = 0; i < NUM_PARTITION_CONTEXTS; ++i) {
       vp9_prob Pnew[PARTITION_TYPES - 1];
       unsigned int bct[PARTITION_TYPES - 1][2];
       update_mode(&header_bc, PARTITION_TYPES, vp9_partition_encodings,
-                  vp9_partition_tree, Pnew, pc->fc.partition_prob[i], bct,
+                  vp9_partition_tree, Pnew,
+                  pc->fc.partition_prob[pc->frame_type][i], bct,
                   (unsigned int *)cpi->partition_count[i]);
     }
 
     vp9_write_nmv_probs(cpi, xd->allow_high_precision_mv, &header_bc);
   }
 
-  /* tiling */
-  {
-    int min_log2_tiles, delta_log2_tiles, n_tile_bits, n;
-
-    vp9_get_tile_n_bits(pc, &min_log2_tiles, &delta_log2_tiles);
-    n_tile_bits = pc->log2_tile_columns - min_log2_tiles;
-    for (n = 0; n < delta_log2_tiles; n++) {
-      if (n_tile_bits--) {
-        vp9_write_bit(&header_bc, 1);
-      } else {
-        vp9_write_bit(&header_bc, 0);
-        break;
-      }
-    }
-    vp9_write_bit(&header_bc, pc->log2_tile_rows != 0);
-    if (pc->log2_tile_rows != 0)
-      vp9_write_bit(&header_bc, pc->log2_tile_rows != 1);
-  }
 
   vp9_stop_encode(&header_bc);
 
diff --git a/vp9/encoder/vp9_boolhuff.c b/vp9/encoder/vp9_boolhuff.c
index 86143ca..0f1aa59 100644
--- a/vp9/encoder/vp9_boolhuff.c
+++ b/vp9/encoder/vp9_boolhuff.c
@@ -47,6 +47,7 @@
   br->count    = -24;
   br->buffer   = source;
   br->pos      = 0;
+  vp9_write_bit(br, 0);
 }
 
 void vp9_stop_encode(vp9_writer *br) {
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index d1666df..8980306 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -330,7 +330,6 @@
                          BLOCK_SIZE_TYPE bsize,
                          int output_enabled) {
   int i, x_idx, y;
-  VP9_COMMON *const cm = &cpi->common;
   MACROBLOCK *const x = &cpi->mb;
   MACROBLOCKD *const xd = &x->e_mbd;
   MODE_INFO *mi = &ctx->mic;
@@ -345,7 +344,8 @@
 #if CONFIG_DEBUG
   assert(mb_mode < MB_MODE_COUNT);
   assert(mb_mode_index < MAX_MODES);
-  assert(mi->mbmi.ref_frame < MAX_REF_FRAMES);
+  assert(mi->mbmi.ref_frame[0] < MAX_REF_FRAMES);
+  assert(mi->mbmi.ref_frame[1] < MAX_REF_FRAMES);
 #endif
 
   assert(mi->mbmi.sb_type == bsize);
@@ -366,7 +366,7 @@
     ctx->txfm_rd_diff[ALLOW_32X32] = ctx->txfm_rd_diff[ALLOW_16X16];
   }
 
-  if (mbmi->ref_frame != INTRA_FRAME && mbmi->sb_type < BLOCK_SIZE_SB8X8) {
+  if (mbmi->ref_frame[0] != INTRA_FRAME && mbmi->sb_type < BLOCK_SIZE_SB8X8) {
     *x->partition_info = ctx->partition_info;
     mbmi->mv[0].as_int = x->partition_info->bmi[3].mv.as_int;
     mbmi->mv[1].as_int = x->partition_info->bmi[3].second_mv.as_int;
@@ -376,29 +376,9 @@
   if (!output_enabled)
     return;
 
-  {
-    int segment_id = mbmi->segment_id, ref_pred_flag;
-    if (!vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP)) {
-      for (i = 0; i < NB_TXFM_MODES; i++) {
-        cpi->rd_tx_select_diff[i] += ctx->txfm_rd_diff[i];
-      }
-    }
-
-    // Did the chosen reference frame match its predicted value.
-    ref_pred_flag = ((xd->mode_info_context->mbmi.ref_frame ==
-                      vp9_get_pred_ref(cm, xd)));
-    vp9_set_pred_flag(xd, PRED_REF, ref_pred_flag);
-    if (!xd->segmentation_enabled ||
-        !vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME) ||
-        vp9_check_segref(xd, segment_id, INTRA_FRAME)  +
-        vp9_check_segref(xd, segment_id, LAST_FRAME)   +
-        vp9_check_segref(xd, segment_id, GOLDEN_FRAME) +
-        vp9_check_segref(xd, segment_id, ALTREF_FRAME) > 1) {
-      // Get the prediction context and status
-      int pred_context = vp9_get_pred_context(cm, xd, PRED_REF);
-
-      // Count prediction success
-      cpi->ref_pred_count[pred_context][ref_pred_flag]++;
+  if (!vp9_segfeature_active(xd, mbmi->segment_id, SEG_LVL_SKIP)) {
+    for (i = 0; i < NB_TXFM_MODES; i++) {
+      cpi->rd_tx_select_diff[i] += ctx->txfm_rd_diff[i];
     }
   }
 
@@ -448,15 +428,16 @@
     */
     // Note how often each mode chosen as best
     cpi->mode_chosen_counts[mb_mode_index]++;
-    if (mbmi->ref_frame != INTRA_FRAME &&
+    if (mbmi->ref_frame[0] != INTRA_FRAME &&
         (mbmi->sb_type < BLOCK_SIZE_SB8X8 || mbmi->mode == NEWMV)) {
       int_mv best_mv, best_second_mv;
-      MV_REFERENCE_FRAME rf = mbmi->ref_frame;
+      const MV_REFERENCE_FRAME rf1 = mbmi->ref_frame[0];
+      const MV_REFERENCE_FRAME rf2 = mbmi->ref_frame[1];
       best_mv.as_int = ctx->best_ref_mv.as_int;
       best_second_mv.as_int = ctx->second_best_ref_mv.as_int;
       if (mbmi->mode == NEWMV) {
-        best_mv.as_int = mbmi->ref_mvs[rf][0].as_int;
-        best_second_mv.as_int = mbmi->ref_mvs[mbmi->second_ref_frame][0].as_int;
+        best_mv.as_int = mbmi->ref_mvs[rf1][0].as_int;
+        best_second_mv.as_int = mbmi->ref_mvs[rf2][0].as_int;
       }
       mbmi->best_mv.as_int = best_mv.as_int;
       mbmi->best_second_mv.as_int = best_second_mv.as_int;
@@ -467,12 +448,14 @@
       int i, j;
       for (j = 0; j < bh; ++j)
         for (i = 0; i < bw; ++i)
-          xd->mode_info_context[mis * j + i].mbmi = *mbmi;
+          if ((xd->mb_to_right_edge >> (3 + LOG2_MI_SIZE)) + bw > i &&
+              (xd->mb_to_bottom_edge >> (3 + LOG2_MI_SIZE)) + bh > j)
+            xd->mode_info_context[mis * j + i].mbmi = *mbmi;
     }
 
     if (cpi->common.mcomp_filter_type == SWITCHABLE &&
         is_inter_mode(mbmi->mode)) {
-      ++cpi->switchable_interp_count
+      ++cpi->common.fc.switchable_interp_count
           [vp9_get_pred_context(&cpi->common, xd, PRED_SWITCHABLE_INTERP)]
           [vp9_switchable_interp_map[mbmi->interp_filter]];
     }
@@ -652,14 +635,8 @@
   if (cm->frame_type != KEY_FRAME) {
     int segment_id, seg_ref_active;
 
-    if (mbmi->ref_frame) {
-      int pred_context = vp9_get_pred_context(cm, xd, PRED_COMP);
-
-      if (mbmi->second_ref_frame <= INTRA_FRAME)
-        cpi->single_pred_count[pred_context]++;
-      else
-        cpi->comp_pred_count[pred_context]++;
-    }
+    cpi->intra_inter_count[vp9_get_pred_context(cm, xd, PRED_INTRA_INTER)]
+                          [mbmi->ref_frame[0] > INTRA_FRAME]++;
 
     // If we have just a single reference frame coded for a segment then
     // exclude from the reference frame counts used to work out
@@ -669,15 +646,31 @@
     segment_id = mbmi->segment_id;
     seg_ref_active = vp9_segfeature_active(xd, segment_id,
                                            SEG_LVL_REF_FRAME);
-    if (!seg_ref_active ||
-        ((vp9_check_segref(xd, segment_id, INTRA_FRAME) +
-          vp9_check_segref(xd, segment_id, LAST_FRAME) +
-          vp9_check_segref(xd, segment_id, GOLDEN_FRAME) +
-          vp9_check_segref(xd, segment_id, ALTREF_FRAME)) > 1)) {
-      cpi->count_mb_ref_frame_usage[mbmi->ref_frame]++;
+    if (mbmi->ref_frame[0] > INTRA_FRAME &&
+        (!seg_ref_active ||
+         ((vp9_check_segref(xd, segment_id, INTRA_FRAME) +
+           vp9_check_segref(xd, segment_id, LAST_FRAME) +
+           vp9_check_segref(xd, segment_id, GOLDEN_FRAME) +
+           vp9_check_segref(xd, segment_id, ALTREF_FRAME)) > 1))) {
+      if (cm->comp_pred_mode == HYBRID_PREDICTION)
+        cpi->comp_inter_count[vp9_get_pred_context(cm, xd,
+                                                   PRED_COMP_INTER_INTER)]
+                             [mbmi->ref_frame[1] > INTRA_FRAME]++;
+
+      if (mbmi->ref_frame[1] > INTRA_FRAME) {
+        cpi->comp_ref_count[vp9_get_pred_context(cm, xd, PRED_COMP_REF_P)]
+                           [mbmi->ref_frame[0] == GOLDEN_FRAME]++;
+      } else {
+        cpi->single_ref_count[vp9_get_pred_context(cm, xd, PRED_SINGLE_REF_P1)]
+                             [0][mbmi->ref_frame[0] != LAST_FRAME]++;
+        if (mbmi->ref_frame[0] != LAST_FRAME)
+          cpi->single_ref_count[vp9_get_pred_context(cm, xd,
+                                                     PRED_SINGLE_REF_P2)]
+                               [1][mbmi->ref_frame[0] != GOLDEN_FRAME]++;
+      }
     }
     // Count of last ref frame 0,0 usage
-    if ((mbmi->mode == ZEROMV) && (mbmi->ref_frame == LAST_FRAME))
+    if ((mbmi->mode == ZEROMV) && (mbmi->ref_frame[0] == LAST_FRAME))
       cpi->inter_zz_count++;
   }
 }
@@ -915,13 +908,16 @@
                            MODE_INFO *m, BLOCK_SIZE_TYPE bsize, int mis,
                            int mi_row, int mi_col) {
   int row, col;
-  int bsl = b_width_log2(bsize);
+  int bwl = b_width_log2(bsize);
+  int bhl = b_height_log2(bsize);
+  int bsl = (bwl > bhl ? bwl : bhl);
+
   int bs = (1 << bsl) / 2;  //
   MODE_INFO *m2 = m + mi_row * mis + mi_col;
   for (row = 0; row < bs; row++) {
     for (col = 0; col < bs; col++) {
       if (mi_row + row >= cm->mi_rows || mi_col + col >= cm->mi_cols)
-        return;
+        continue;
       m2[row*mis+col].mbmi.sb_type = bsize;
     }
   }
@@ -961,21 +957,6 @@
       / v->count;
 }
 
-// Fills a 16x16 variance tree node by calling get var8x8 var..
-static void fill_16x16_variance(const unsigned char *s, int sp,
-                                const unsigned char *d, int dp, v16x16 *vt) {
-  unsigned int sse;
-  int sum;
-  vp9_get_sse_sum_8x8(s, sp, d, dp, &sse, &sum);
-  fill_variance(&vt->split[0].none, sse, sum, 64);
-  vp9_get_sse_sum_8x8(s + 8, sp, d + 8, dp, &sse, &sum);
-  fill_variance(&vt->split[1].none, sse, sum, 64);
-  vp9_get_sse_sum_8x8(s + 8 * sp, sp, d + 8 * dp, dp, &sse, &sum);
-  fill_variance(&vt->split[2].none, sse, sum, 64);
-  vp9_get_sse_sum_8x8(s + 8 * sp + 8, sp, d + 8 + 8 * dp, dp, &sse, &sum);
-  fill_variance(&vt->split[3].none, sse, sum, 64);
-}
-
 // Combine 2 variance structures by summing the sum_error, sum_square_error,
 // and counts and then calculating the new variance.
 void sum_2_variances(var *r, var *a, var*b) {
@@ -1021,8 +1002,18 @@
   int sp;
   const unsigned char * d = xd->plane[0].pre->buf;
   int dp = xd->plane[0].pre->stride;
+  int pixels_wide = 64, pixels_high = 64;
+
+  vpx_memset(&vt, 0, sizeof(vt));
 
   set_offsets(cpi, mi_row, mi_col, BLOCK_SIZE_SB64X64);
+
+  if (xd->mb_to_right_edge < 0)
+    pixels_wide += (xd->mb_to_right_edge >> 3);
+
+  if (xd->mb_to_bottom_edge < 0)
+    pixels_high += (xd->mb_to_bottom_edge >> 3);
+
   s = x->plane[0].src.buf;
   sp = x->plane[0].src.stride;
 
@@ -1034,6 +1025,7 @@
   d = vp9_64x64_zeros;
   dp = 64;
   // }
+
   // Fill in the entire tree of 8x8 variances for splits.
   for (i = 0; i < 4; i++) {
     const int x32_idx = ((i & 1) << 5);
@@ -1041,8 +1033,28 @@
     for (j = 0; j < 4; j++) {
       const int x_idx = x32_idx + ((j & 1) << 4);
       const int y_idx = y32_idx + ((j >> 1) << 4);
-      fill_16x16_variance(s + y_idx * sp + x_idx, sp, d + y_idx * dp + x_idx,
-                          dp, &vt.split[i].split[j]);
+      const uint8_t *st = s + y_idx * sp + x_idx;
+      const uint8_t *dt = d + y_idx * dp + x_idx;
+      unsigned int sse = 0;
+      int sum = 0;
+      v16x16 *vst = &vt.split[i].split[j];
+      sse = sum = 0;
+      if (x_idx < pixels_wide && y_idx < pixels_high)
+        vp9_get_sse_sum_8x8(st, sp, dt, dp, &sse, &sum);
+      fill_variance(&vst->split[0].none, sse, sum, 64);
+      sse = sum = 0;
+      if (x_idx + 8 < pixels_wide && y_idx < pixels_high)
+        vp9_get_sse_sum_8x8(st + 8, sp, dt + 8, dp, &sse, &sum);
+      fill_variance(&vst->split[1].none, sse, sum, 64);
+      sse = sum = 0;
+      if (x_idx < pixels_wide && y_idx + 8 < pixels_high)
+        vp9_get_sse_sum_8x8(st + 8 * sp, sp, dt + 8 * dp, dp, &sse, &sum);
+      fill_variance(&vst->split[2].none, sse, sum, 64);
+      sse = sum = 0;
+      if (x_idx + 8 < pixels_wide && y_idx + 8 < pixels_high)
+        vp9_get_sse_sum_8x8(st + 8 * sp + 8, sp, dt + 8 + 8 * dp, dp, &sse,
+                            &sum);
+      fill_variance(&vst->split[3].none, sse, sum, 64);
     }
   }
   // Fill the rest of the variance tree by summing the split partition
@@ -1088,8 +1100,10 @@
   MACROBLOCK * const x = &cpi->mb;
   MACROBLOCKD *xd = &cpi->mb.e_mbd;
   const int mis = cm->mode_info_stride;
-  int bwl, bhl;
+  int bwl = b_width_log2(m->mbmi.sb_type);
+  int bhl = b_height_log2(m->mbmi.sb_type);
   int bsl = b_width_log2(bsize);
+  int bh = (1 << bhl);
   int bs = (1 << bsl);
   int bss = (1 << bsl)/4;
   int i, pl;
@@ -1103,9 +1117,6 @@
     return;
 
 
-  bwl = b_width_log2(m->mbmi.sb_type);
-  bhl = b_height_log2(m->mbmi.sb_type);
-
   // parse the partition type
   if ((bwl == bsl) && (bhl == bsl))
     partition = PARTITION_NONE;
@@ -1144,7 +1155,7 @@
       *(get_sb_index(xd, subsize)) = 0;
       pick_sb_modes(cpi, mi_row, mi_col, tp, &r, &d, subsize,
                     get_block_context(x, subsize));
-      if (mi_row + (bs >> 1) <= cm->mi_rows) {
+      if (mi_row + (bh >> 1) <= cm->mi_rows) {
         int rt, dt;
         update_state(cpi, get_block_context(x, subsize), subsize, 0);
         encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize);
@@ -1404,18 +1415,13 @@
   for (mi_col = cm->cur_tile_mi_col_start;
        mi_col < cm->cur_tile_mi_col_end; mi_col += 8) {
     int dummy_rate, dummy_dist;
-    // TODO(JBB): remove the border conditions for 64x64 blocks once its fixed
-    // without this border check choose will fail on the border of every
-    // non 64x64.
-    if (cpi->speed < 5 ||
-        mi_col + 8 > cm->cur_tile_mi_col_end ||
-        mi_row + 8 > cm->cur_tile_mi_row_end) {
+    if (cpi->speed < 5) {
       rd_pick_partition(cpi, tp, mi_row, mi_col, BLOCK_SIZE_SB64X64,
                         &dummy_rate, &dummy_dist);
     } else {
       const int idx_str = cm->mode_info_stride * mi_row + mi_col;
       MODE_INFO *m = cm->mi + idx_str;
-      // set_partitioning(cpi, m, BLOCK_SIZE_SB8X8);
+      // set_partitioning(cpi, m, BLOCK_SIZE_SB64X64);
       choose_partitioning(cpi, cm->mi, mi_row, mi_col);
       rd_use_partition(cpi, m, tp, mi_row, mi_col, BLOCK_SIZE_SB64X64,
                        &dummy_rate, &dummy_dist);
@@ -1430,7 +1436,6 @@
 
   x->act_zbin_adj = 0;
   cpi->seg0_idx = 0;
-  vpx_memset(cpi->ref_pred_count, 0, sizeof(cpi->ref_pred_count));
 
   xd->mode_info_stride = cm->mode_info_stride;
   xd->frame_type = cm->frame_type;
@@ -1457,11 +1462,17 @@
   xd->mode_info_context->mbmi.mode = DC_PRED;
   xd->mode_info_context->mbmi.uv_mode = DC_PRED;
 
-  vp9_zero(cpi->count_mb_ref_frame_usage)
   vp9_zero(cpi->y_mode_count)
   vp9_zero(cpi->y_uv_mode_count)
-  vp9_zero(cpi->common.fc.mv_ref_ct)
+  vp9_zero(cm->fc.inter_mode_counts)
   vp9_zero(cpi->partition_count);
+  vp9_zero(cpi->intra_inter_count);
+  vp9_zero(cpi->comp_inter_count);
+  vp9_zero(cpi->single_ref_count);
+  vp9_zero(cpi->comp_ref_count);
+  vp9_zero(cm->fc.tx_count_32x32p);
+  vp9_zero(cm->fc.tx_count_16x16p);
+  vp9_zero(cm->fc.tx_count_8x8p);
 
   // Note: this memset assumes above_context[0], [1] and [2]
   // are allocated as part of the same buffer.
@@ -1501,11 +1512,6 @@
 //           cpi->common.current_video_frame, cpi->common.show_frame,
 //           cm->frame_type);
 
-  // Compute a modified set of reference frame probabilities to use when
-  // prediction fails. These are based on the current general estimates for
-  // this frame which may be updated with each iteration of the recode loop.
-  vp9_compute_mod_refprobs(cm);
-
 // debug output
 #if DBG_PRNT_SEGMAP
   {
@@ -1524,7 +1530,7 @@
   cpi->skip_true_count[0] = cpi->skip_true_count[1] = cpi->skip_true_count[2] = 0;
   cpi->skip_false_count[0] = cpi->skip_false_count[1] = cpi->skip_false_count[2] = 0;
 
-  vp9_zero(cpi->switchable_interp_count);
+  vp9_zero(cm->fc.switchable_interp_count);
   vp9_zero(cpi->best_switchable_interp_count);
 
   xd->mode_info_context = cm->mi;
@@ -1557,11 +1563,6 @@
   init_encode_frame_mb_context(cpi);
 
   vpx_memset(cpi->rd_comp_pred_diff, 0, sizeof(cpi->rd_comp_pred_diff));
-  vpx_memset(cpi->single_pred_count, 0, sizeof(cpi->single_pred_count));
-  vpx_memset(cpi->comp_pred_count, 0, sizeof(cpi->comp_pred_count));
-  vpx_memset(cpi->txfm_count_32x32p, 0, sizeof(cpi->txfm_count_32x32p));
-  vpx_memset(cpi->txfm_count_16x16p, 0, sizeof(cpi->txfm_count_16x16p));
-  vpx_memset(cpi->txfm_count_8x8p, 0, sizeof(cpi->txfm_count_8x8p));
   vpx_memset(cpi->rd_tx_select_diff, 0, sizeof(cpi->rd_tx_select_diff));
   vpx_memset(cpi->rd_tx_select_threshes, 0, sizeof(cpi->rd_tx_select_threshes));
 
@@ -1749,6 +1750,26 @@
 }
 
 void vp9_encode_frame(VP9_COMP *cpi) {
+  VP9_COMMON *const cm = &cpi->common;
+
+  // In the longer term the encoder should be generalized to match the
+  // decoder such that we allow compound where one of the 3 buffers has a
+  // differnt sign bias and that buffer is then the fixed ref. However, this
+  // requires further work in the rd loop. For now the only supported encoder
+  // side behaviour is where the ALT ref buffer has oppositie sign bias to
+  // the other two.
+  if ((cm->ref_frame_sign_bias[ALTREF_FRAME] ==
+       cm->ref_frame_sign_bias[GOLDEN_FRAME]) ||
+      (cm->ref_frame_sign_bias[ALTREF_FRAME] ==
+       cm->ref_frame_sign_bias[LAST_FRAME])) {
+    cm->allow_comp_inter_inter = 0;
+  } else {
+    cm->allow_comp_inter_inter = 1;
+    cm->comp_fixed_ref = ALTREF_FRAME;
+    cm->comp_var_ref[0] = LAST_FRAME;
+    cm->comp_var_ref[1] = GOLDEN_FRAME;
+  }
+
   if (cpi->sf.RD) {
     int i, frame_type, pred_type;
     TXFM_MODE txfm_type;
@@ -1772,7 +1793,7 @@
       frame_type = 2;
 
     /* prediction (compound, single or hybrid) mode selection */
-    if (frame_type == 3)
+    if (frame_type == 3 || !cm->allow_comp_inter_inter)
       pred_type = SINGLE_PREDICTION_ONLY;
     else if (cpi->rd_prediction_type_threshes[frame_type][1] >
                  cpi->rd_prediction_type_threshes[frame_type][0] &&
@@ -1826,11 +1847,6 @@
                     ALLOW_32X32 : TX_MODE_SELECT;
 #endif
     cpi->common.txfm_mode = txfm_type;
-    if (txfm_type != TX_MODE_SELECT) {
-      cpi->common.prob_tx[0] = 128;
-      cpi->common.prob_tx[1] = 128;
-      cpi->common.prob_tx[2] = 128;
-    }
     cpi->common.comp_pred_mode = pred_type;
     encode_frame_internal(cpi);
 
@@ -1855,28 +1871,30 @@
       int single_count_zero = 0;
       int comp_count_zero = 0;
 
-      for (i = 0; i < COMP_PRED_CONTEXTS; i++) {
-        single_count_zero += cpi->single_pred_count[i];
-        comp_count_zero += cpi->comp_pred_count[i];
+      for (i = 0; i < COMP_INTER_CONTEXTS; i++) {
+        single_count_zero += cpi->comp_inter_count[i][0];
+        comp_count_zero += cpi->comp_inter_count[i][1];
       }
 
       if (comp_count_zero == 0) {
         cpi->common.comp_pred_mode = SINGLE_PREDICTION_ONLY;
+        vp9_zero(cpi->comp_inter_count);
       } else if (single_count_zero == 0) {
         cpi->common.comp_pred_mode = COMP_PREDICTION_ONLY;
+        vp9_zero(cpi->comp_inter_count);
       }
     }
 
     if (cpi->common.txfm_mode == TX_MODE_SELECT) {
-      const int count4x4 = cpi->txfm_count_16x16p[TX_4X4] +
-                           cpi->txfm_count_32x32p[TX_4X4] +
-                           cpi->txfm_count_8x8p[TX_4X4];
-      const int count8x8_lp = cpi->txfm_count_32x32p[TX_8X8] +
-                              cpi->txfm_count_16x16p[TX_8X8];
-      const int count8x8_8x8p = cpi->txfm_count_8x8p[TX_8X8];
-      const int count16x16_16x16p = cpi->txfm_count_16x16p[TX_16X16];
-      const int count16x16_lp = cpi->txfm_count_32x32p[TX_16X16];
-      const int count32x32 = cpi->txfm_count_32x32p[TX_32X32];
+      const int count4x4 = cm->fc.tx_count_16x16p[TX_4X4] +
+                           cm->fc.tx_count_32x32p[TX_4X4] +
+                           cm->fc.tx_count_8x8p[TX_4X4];
+      const int count8x8_lp = cm->fc.tx_count_32x32p[TX_8X8] +
+                              cm->fc.tx_count_16x16p[TX_8X8];
+      const int count8x8_8x8p = cm->fc.tx_count_8x8p[TX_8X8];
+      const int count16x16_16x16p = cm->fc.tx_count_16x16p[TX_16X16];
+      const int count16x16_lp = cm->fc.tx_count_32x32p[TX_16X16];
+      const int count32x32 = cm->fc.tx_count_32x32p[TX_32X32];
 
       if (count4x4 == 0 && count16x16_lp == 0 && count16x16_16x16p == 0 &&
           count32x32 == 0) {
@@ -1913,7 +1931,10 @@
 
   ++cpi->y_uv_mode_count[m][uvm];
   if (xd->mode_info_context->mbmi.sb_type >= BLOCK_SIZE_SB8X8) {
-    ++cpi->y_mode_count[m];
+    const BLOCK_SIZE_TYPE bsize = xd->mode_info_context->mbmi.sb_type;
+    const int bwl = b_width_log2(bsize), bhl = b_height_log2(bsize);
+    const int bsl = MIN(bwl, bhl);
+    ++cpi->y_mode_count[MIN(bsl, 3)][m];
   } else {
     int idx, idy;
     int bw = 1 << b_width_log2(xd->mode_info_context->mbmi.sb_type);
@@ -1921,7 +1942,7 @@
     for (idy = 0; idy < 2; idy += bh) {
       for (idx = 0; idx < 2; idx += bw) {
         int m = xd->mode_info_context->bmi[idy * 2 + idx].as_mode.first;
-        ++cpi->y_mode_count[m];
+        ++cpi->y_mode_count[0][m];
       }
     }
   }
@@ -1979,9 +2000,9 @@
     // Increase zbin size to suppress noise
     cpi->zbin_mode_boost = 0;
     if (cpi->zbin_mode_boost_enabled) {
-      if (mbmi->ref_frame != INTRA_FRAME) {
+      if (mbmi->ref_frame[0] != INTRA_FRAME) {
         if (mbmi->mode == ZEROMV) {
-          if (mbmi->ref_frame != LAST_FRAME)
+          if (mbmi->ref_frame[0] != LAST_FRAME)
             cpi->zbin_mode_boost = GF_ZEROMV_ZBIN_BOOST;
           else
             cpi->zbin_mode_boost = LF_ZEROMV_ZBIN_BOOST;
@@ -1998,7 +2019,7 @@
     vp9_update_zbin_extra(cpi, x);
   }
 
-  if (mbmi->ref_frame == INTRA_FRAME) {
+  if (mbmi->ref_frame[0] == INTRA_FRAME) {
     vp9_encode_intra_block_y(cm, x, (bsize < BLOCK_SIZE_SB8X8) ?
                                     BLOCK_SIZE_SB8X8 : bsize);
     vp9_encode_intra_block_uv(cm, x, (bsize < BLOCK_SIZE_SB8X8) ?
@@ -2006,11 +2027,11 @@
     if (output_enabled)
       sum_intra_stats(cpi, x);
   } else {
-    int idx = cm->ref_frame_map[get_ref_frame_idx(cpi, mbmi->ref_frame)];
+    int idx = cm->ref_frame_map[get_ref_frame_idx(cpi, mbmi->ref_frame[0])];
     YV12_BUFFER_CONFIG *ref_fb = &cm->yv12_fb[idx];
     YV12_BUFFER_CONFIG *second_ref_fb = NULL;
-    if (mbmi->second_ref_frame > 0) {
-      idx = cm->ref_frame_map[get_ref_frame_idx(cpi, mbmi->second_ref_frame)];
+    if (mbmi->ref_frame[1] > 0) {
+      idx = cm->ref_frame_map[get_ref_frame_idx(cpi, mbmi->ref_frame[1])];
       second_ref_fb = &cm->yv12_fb[idx];
     }
 
@@ -2024,7 +2045,7 @@
                                                            : bsize);
   }
 
-  if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) {
+  if (xd->mode_info_context->mbmi.ref_frame[0] == INTRA_FRAME) {
     vp9_tokenize_sb(cpi, xd, t, !output_enabled,
                     (bsize < BLOCK_SIZE_SB8X8) ? BLOCK_SIZE_SB8X8 : bsize);
   } else if (!x->skip) {
@@ -2054,20 +2075,20 @@
   if (output_enabled) {
     if (cm->txfm_mode == TX_MODE_SELECT &&
         mbmi->sb_type >= BLOCK_SIZE_SB8X8 &&
-        !(mbmi->ref_frame != INTRA_FRAME && (mbmi->mb_skip_coeff ||
+        !(mbmi->ref_frame[0] != INTRA_FRAME && (mbmi->mb_skip_coeff ||
           vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP)))) {
       if (bsize >= BLOCK_SIZE_SB32X32) {
-        cpi->txfm_count_32x32p[mbmi->txfm_size]++;
+        cm->fc.tx_count_32x32p[mbmi->txfm_size]++;
       } else if (bsize >= BLOCK_SIZE_MB16X16) {
-        cpi->txfm_count_16x16p[mbmi->txfm_size]++;
+        cm->fc.tx_count_16x16p[mbmi->txfm_size]++;
       } else {
-        cpi->txfm_count_8x8p[mbmi->txfm_size]++;
+        cm->fc.tx_count_8x8p[mbmi->txfm_size]++;
       }
     } else {
       int x, y;
       TX_SIZE sz = (cm->txfm_mode == TX_MODE_SELECT) ? TX_32X32 : cm->txfm_mode;
        // The new intra coding scheme requires no change of transform size
-      if (mi->mbmi.ref_frame != INTRA_FRAME) {
+      if (mi->mbmi.ref_frame[0] != INTRA_FRAME) {
         if (sz == TX_32X32 && bsize < BLOCK_SIZE_SB32X32)
           sz = TX_16X16;
         if (sz == TX_16X16 && bsize < BLOCK_SIZE_MB16X16)
diff --git a/vp9/encoder/vp9_encodeintra.c b/vp9/encoder/vp9_encodeintra.c
index 57041a9..c78882a 100644
--- a/vp9/encoder/vp9_encodeintra.c
+++ b/vp9/encoder/vp9_encodeintra.c
@@ -20,7 +20,7 @@
   MB_MODE_INFO * mbmi = &x->e_mbd.mode_info_context->mbmi;
   (void) cpi;
   mbmi->mode = DC_PRED;
-  mbmi->ref_frame = INTRA_FRAME;
+  mbmi->ref_frame[0] = INTRA_FRAME;
   if (use_16x16_pred) {
     mbmi->txfm_size = TX_16X16;
     vp9_encode_intra_block_y(&cpi->common, x, BLOCK_SIZE_MB16X16);
diff --git a/vp9/encoder/vp9_encodemb.c b/vp9/encoder/vp9_encodemb.c
index 389c5d8..aa9cf8d 100644
--- a/vp9/encoder/vp9_encodemb.c
+++ b/vp9/encoder/vp9_encodemb.c
@@ -118,7 +118,7 @@
                        int plane, int block, BLOCK_SIZE_TYPE bsize,
                        ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l,
                        TX_SIZE tx_size) {
-  const int ref = mb->e_mbd.mode_info_context->mbmi.ref_frame != INTRA_FRAME;
+  const int ref = mb->e_mbd.mode_info_context->mbmi.ref_frame[0] != INTRA_FRAME;
   MACROBLOCKD *const xd = &mb->e_mbd;
   vp9_token_state tokens[1025][2];
   unsigned best_index[1025][2];
@@ -179,7 +179,7 @@
 
   /* Now set up a Viterbi trellis to evaluate alternative roundings. */
   rdmult = mb->rdmult * err_mult;
-  if (mb->e_mbd.mode_info_context->mbmi.ref_frame == INTRA_FRAME)
+  if (mb->e_mbd.mode_info_context->mbmi.ref_frame[0] == INTRA_FRAME)
     rdmult = (rdmult * 9) >> 4;
   rddiv = mb->rddiv;
   memset(best_index, 0, sizeof(best_index));
@@ -615,10 +615,14 @@
   TX_TYPE tx_type;
   int mode, b_mode;
 
+  if (xd->mb_to_right_edge < 0 || xd->mb_to_bottom_edge < 0) {
+    extend_for_intra(xd, plane, block, bsize, ss_txfrm_size);
+  }
+
   mode = plane == 0? mbmi->mode: mbmi->uv_mode;
   if (plane == 0 &&
       mbmi->sb_type < BLOCK_SIZE_SB8X8 &&
-      mbmi->ref_frame == INTRA_FRAME)
+      mbmi->ref_frame[0] == INTRA_FRAME)
     b_mode = xd->mode_info_context->bmi[ib].as_mode.first;
   else
     b_mode = mode;
@@ -684,7 +688,6 @@
   MACROBLOCKD* const xd = &x->e_mbd;
   struct optimize_ctx ctx;
   struct encode_b_args arg = {cm, x, &ctx};
-
   foreach_transformed_block_uv(xd, bsize, encode_block_intra, &arg);
 }
 
diff --git a/vp9/encoder/vp9_encodemv.c b/vp9/encoder/vp9_encodemv.c
index 2b6dfba..a582d18 100644
--- a/vp9/encoder/vp9_encodemv.c
+++ b/vp9/encoder/vp9_encodemv.c
@@ -584,7 +584,7 @@
           mv.col = (pi->bmi[i].mv.as_mv.col - best_ref_mv->as_mv.col);
           vp9_increment_nmv(&mv, &best_ref_mv->as_mv, &cpi->NMVcount,
                             x->e_mbd.allow_high_precision_mv);
-          if (x->e_mbd.mode_info_context->mbmi.second_ref_frame > 0) {
+          if (x->e_mbd.mode_info_context->mbmi.ref_frame[1] > INTRA_FRAME) {
             mv.row = pi->bmi[i].second_mv.as_mv.row -
                          second_best_ref_mv->as_mv.row;
             mv.col = pi->bmi[i].second_mv.as_mv.col -
@@ -600,7 +600,7 @@
     mv.col = (mbmi->mv[0].as_mv.col - best_ref_mv->as_mv.col);
     vp9_increment_nmv(&mv, &best_ref_mv->as_mv, &cpi->NMVcount,
                       x->e_mbd.allow_high_precision_mv);
-    if (mbmi->second_ref_frame > 0) {
+    if (mbmi->ref_frame[1] > INTRA_FRAME) {
       mv.row = (mbmi->mv[1].as_mv.row - second_best_ref_mv->as_mv.row);
       mv.col = (mbmi->mv[1].as_mv.col - second_best_ref_mv->as_mv.col);
       vp9_increment_nmv(&mv, &second_best_ref_mv->as_mv, &cpi->NMVcount,
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index b07e37d..001129d 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -523,7 +523,7 @@
       xd->left_available = (mb_col != 0);
 
       xd->mode_info_context->mbmi.sb_type = BLOCK_SIZE_MB16X16;
-      xd->mode_info_context->mbmi.ref_frame = INTRA_FRAME;
+      xd->mode_info_context->mbmi.ref_frame[0] = INTRA_FRAME;
 
       // do intra 16x16 prediction
       this_error = vp9_encode_intra(cpi, x, use_dc_pred);
@@ -620,7 +620,8 @@
           this_error = motion_error;
           vp9_set_mbmode_and_mvs(x, NEWMV, &mv);
           xd->mode_info_context->mbmi.txfm_size = TX_4X4;
-          xd->mode_info_context->mbmi.ref_frame = LAST_FRAME;
+          xd->mode_info_context->mbmi.ref_frame[0] = LAST_FRAME;
+          xd->mode_info_context->mbmi.ref_frame[1] = NONE;
           vp9_build_inter_predictors_sby(xd, mb_row << 1,
                                          mb_col << 1,
                                          BLOCK_SIZE_MB16X16);
diff --git a/vp9/encoder/vp9_modecosts.c b/vp9/encoder/vp9_modecosts.c
index 099a044..f2e4ce4 100644
--- a/vp9/encoder/vp9_modecosts.c
+++ b/vp9/encoder/vp9_modecosts.c
@@ -28,7 +28,7 @@
   }
 
   // TODO(rbultje) separate tables for superblock costing?
-  vp9_cost_tokens(c->mb.mbmode_cost, x->fc.y_mode_prob,
+  vp9_cost_tokens(c->mb.mbmode_cost, x->fc.y_mode_prob[1],
                   vp9_intra_mode_tree);
   vp9_cost_tokens(c->mb.intra_uv_mode_cost[1],
                   x->fc.uv_mode_prob[VP9_INTRA_MODES - 1], vp9_intra_mode_tree);
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index a5659d6..73220dc 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -466,8 +466,9 @@
 void vp9_update_mode_context_stats(VP9_COMP *cpi) {
   VP9_COMMON *cm = &cpi->common;
   int i, j;
-  unsigned int (*mv_ref_ct)[VP9_MVREFS - 1][2] = cm->fc.mv_ref_ct;
-  int64_t (*mv_ref_stats)[VP9_MVREFS - 1][2] = cpi->mv_ref_stats;
+  unsigned int (*inter_mode_counts)[VP9_INTER_MODES - 1][2] =
+      cm->fc.inter_mode_counts;
+  int64_t (*mv_ref_stats)[VP9_INTER_MODES - 1][2] = cpi->mv_ref_stats;
   FILE *f;
 
   // Read the past stats counters
@@ -481,9 +482,9 @@
 
   // Add in the values for this frame
   for (i = 0; i < INTER_MODE_CONTEXTS; i++) {
-    for (j = 0; j < VP9_MVREFS - 1; j++) {
-      mv_ref_stats[i][j][0] += (int64_t)mv_ref_ct[i][j][0];
-      mv_ref_stats[i][j][1] += (int64_t)mv_ref_ct[i][j][1];
+    for (j = 0; j < VP9_INTER_MODES - 1; j++) {
+      mv_ref_stats[i][j][0] += (int64_t)inter_mode_counts[i][j][0];
+      mv_ref_stats[i][j][1] += (int64_t)inter_mode_counts[i][j][1];
     }
   }
 
@@ -498,13 +499,14 @@
   int i, j;
 
   fprintf(f, "#include \"vp9_entropy.h\"\n");
-  fprintf(f,
-          "const int vp9_mode_contexts[INTER_MODE_CONTEXTS][VP9_MVREFS - 1] =");
+  fprintf(
+      f,
+      "const int inter_mode_probs[INTER_MODE_CONTEXTS][VP9_INTER_MODES - 1] =");
   fprintf(f, "{\n");
   for (j = 0; j < INTER_MODE_CONTEXTS; j++) {
     fprintf(f, "  {/* %d */ ", j);
     fprintf(f, "    ");
-    for (i = 0; i < VP9_MVREFS - 1; i++) {
+    for (i = 0; i < VP9_INTER_MODES - 1; i++) {
       int this_prob;
       int64_t count = cpi->mv_ref_stats[j][i][0] + cpi->mv_ref_stats[j][i][1];
       if (count)
@@ -573,10 +575,8 @@
   cpi->mb.e_mbd.ref_lf_deltas[GOLDEN_FRAME] = -2;
   cpi->mb.e_mbd.ref_lf_deltas[ALTREF_FRAME] = -2;
 
-  cpi->mb.e_mbd.mode_lf_deltas[0] = 4;               // I4X4_PRED
-  cpi->mb.e_mbd.mode_lf_deltas[1] = -2;              // Zero
-  cpi->mb.e_mbd.mode_lf_deltas[2] = 2;               // New mv
-  cpi->mb.e_mbd.mode_lf_deltas[3] = 4;               // Split mv
+  cpi->mb.e_mbd.mode_lf_deltas[0] = 0;              // Zero
+  cpi->mb.e_mbd.mode_lf_deltas[1] = 0;               // New mv
 }
 
 static void set_rd_speed_thresholds(VP9_COMP *cpi, int mode, int speed) {
@@ -621,25 +621,20 @@
   sf->thresh_mult[THR_SPLITG   ] += speed_multiplier * 2500;
   sf->thresh_mult[THR_SPLITA   ] += speed_multiplier * 2500;
 
-  sf->thresh_mult[THR_COMP_ZEROLG   ] += speed_multiplier * 1500;
   sf->thresh_mult[THR_COMP_ZEROLA   ] += speed_multiplier * 1500;
   sf->thresh_mult[THR_COMP_ZEROGA   ] += speed_multiplier * 1500;
 
-  sf->thresh_mult[THR_COMP_NEARESTLG] += speed_multiplier * 1500;
   sf->thresh_mult[THR_COMP_NEARESTLA] += speed_multiplier * 1500;
   sf->thresh_mult[THR_COMP_NEARESTGA] += speed_multiplier * 1500;
 
-  sf->thresh_mult[THR_COMP_NEARLG   ] += speed_multiplier * 1500;
   sf->thresh_mult[THR_COMP_NEARLA   ] += speed_multiplier * 1500;
   sf->thresh_mult[THR_COMP_NEARGA   ] += speed_multiplier * 1500;
 
-  sf->thresh_mult[THR_COMP_NEWLG    ] += speed_multiplier * 2000;
   sf->thresh_mult[THR_COMP_NEWLA    ] += speed_multiplier * 2000;
   sf->thresh_mult[THR_COMP_NEWGA    ] += speed_multiplier * 2000;
 
   sf->thresh_mult[THR_COMP_SPLITLA  ] += speed_multiplier * 4500;
   sf->thresh_mult[THR_COMP_SPLITGA  ] += speed_multiplier * 4500;
-  sf->thresh_mult[THR_COMP_SPLITLG  ] += speed_multiplier * 4500;
 
   if (speed > 4) {
     for (i = 0; i < MAX_MODES; ++i)
@@ -683,14 +678,6 @@
     sf->thresh_mult[THR_SPLITA   ] = INT_MAX;
   }
 
-  if ((cpi->ref_frame_flags & (VP9_LAST_FLAG | VP9_GOLD_FLAG)) !=
-      (VP9_LAST_FLAG | VP9_GOLD_FLAG)) {
-    sf->thresh_mult[THR_COMP_ZEROLG   ] = INT_MAX;
-    sf->thresh_mult[THR_COMP_NEARESTLG] = INT_MAX;
-    sf->thresh_mult[THR_COMP_NEARLG   ] = INT_MAX;
-    sf->thresh_mult[THR_COMP_NEWLG    ] = INT_MAX;
-    sf->thresh_mult[THR_COMP_SPLITLG  ] = INT_MAX;
-  }
   if ((cpi->ref_frame_flags & (VP9_LAST_FLAG | VP9_ALT_FLAG)) !=
       (VP9_LAST_FLAG | VP9_ALT_FLAG)) {
     sf->thresh_mult[THR_COMP_ZEROLA   ] = INT_MAX;
@@ -734,18 +721,18 @@
   sf->quarter_pixel_search = 1;
   sf->half_pixel_search = 1;
   sf->iterative_sub_pixel = 1;
-  sf->no_skip_block4x4_search = 1;
   sf->optimize_coefficients = !cpi->oxcf.lossless;
   sf->first_step = 0;
   sf->max_step_search_steps = MAX_MVSEARCH_STEPS;
-  sf->comp_inter_joint_search = 1;
+  sf->comp_inter_joint_search_thresh = BLOCK_SIZE_AB4X4;
+  sf->adpative_rd_thresh = 0;
+
 #if CONFIG_MULTIPLE_ARF
   // Switch segmentation off.
   sf->static_segmentation = 0;
 #else
   sf->static_segmentation = 0;
 #endif
-  sf->mb16_breakout = 0;
 
   switch (mode) {
     case 0: // best quality mode
@@ -757,14 +744,13 @@
       // Switch segmentation off.
       sf->static_segmentation = 0;
 #else
-  sf->static_segmentation = 0;
+      sf->static_segmentation = 0;
 #endif
-      sf->mb16_breakout = 0;
-
+      sf->comp_inter_joint_search_thresh = BLOCK_SIZE_SB8X8;
+      sf->adpative_rd_thresh = 1;
       if (speed > 0) {
+        sf->comp_inter_joint_search_thresh = BLOCK_SIZE_TYPES;
         sf->optimize_coefficients = 0;
-        sf->no_skip_block4x4_search = 0;
-        sf->comp_inter_joint_search = 0;
         sf->first_step = 1;
       }
       break;
@@ -1310,20 +1296,6 @@
   cpi->frames_till_gf_update_due    = 0;
   cpi->gf_overspend_bits            = 0;
   cpi->non_gf_bitrate_adjustment    = 0;
-  cm->prob_last_coded               = 128;
-  cm->prob_gf_coded                 = 128;
-  cm->prob_intra_coded              = 63;
-  for (i = 0; i < COMP_PRED_CONTEXTS; i++)
-    cm->prob_comppred[i]         = 128;
-  for (i = 0; i < TX_SIZE_MAX_SB - 1; i++)
-    cm->prob_tx[i]               = 128;
-
-  // Prime the recent reference frame usage counters.
-  // Hereafter they will be maintained as a sort of moving average
-  cpi->recent_ref_frame_usage[INTRA_FRAME]  = 1;
-  cpi->recent_ref_frame_usage[LAST_FRAME]   = 1;
-  cpi->recent_ref_frame_usage[GOLDEN_FRAME] = 1;
-  cpi->recent_ref_frame_usage[ALTREF_FRAME] = 1;
 
   // Set reference frame sign bias for ALTREF frame to 1 (for now)
   cpi->common.ref_frame_sign_bias[ALTREF_FRAME] = 1;
@@ -2082,22 +2054,6 @@
     cpi->refresh_golden_frame = 0;
     cpi->common.frames_since_golden = 0;
 
-    // if ( cm->frame_type == KEY_FRAME )
-    // {
-    cpi->recent_ref_frame_usage[INTRA_FRAME] = 1;
-    cpi->recent_ref_frame_usage[LAST_FRAME] = 1;
-    cpi->recent_ref_frame_usage[GOLDEN_FRAME] = 1;
-    cpi->recent_ref_frame_usage[ALTREF_FRAME] = 1;
-    // }
-    // else
-    // {
-    //  // Carry a portion of count over to beginning of next gf sequence
-    //  cpi->recent_ref_frame_usage[INTRA_FRAME] >>= 5;
-    //  cpi->recent_ref_frame_usage[LAST_FRAME] >>= 5;
-    //  cpi->recent_ref_frame_usage[GOLDEN_FRAME] >>= 5;
-    //  cpi->recent_ref_frame_usage[ALTREF_FRAME] >>= 5;
-    // }
-
     // ******** Fixed Q test code only ************
     // If we are going to use the ALT reference for the next group of frames set a flag to say so.
     if (cpi->oxcf.fixed_q >= 0 &&
@@ -2122,13 +2078,6 @@
       cpi->common.frames_till_alt_ref_frame--;
 
     cpi->common.frames_since_golden++;
-
-    if (cpi->common.frames_since_golden > 1) {
-      cpi->recent_ref_frame_usage[INTRA_FRAME] += cpi->count_mb_ref_frame_usage[INTRA_FRAME];
-      cpi->recent_ref_frame_usage[LAST_FRAME] += cpi->count_mb_ref_frame_usage[LAST_FRAME];
-      cpi->recent_ref_frame_usage[GOLDEN_FRAME] += cpi->count_mb_ref_frame_usage[GOLDEN_FRAME];
-      cpi->recent_ref_frame_usage[ALTREF_FRAME] += cpi->count_mb_ref_frame_usage[ALTREF_FRAME];
-    }
   }
 }
 
@@ -3112,6 +3061,10 @@
     vp9_copy(cpi->common.fc.y_mode_counts, cpi->y_mode_count);
     vp9_copy(cpi->common.fc.uv_mode_counts, cpi->y_uv_mode_count);
     vp9_copy(cpi->common.fc.partition_counts, cpi->partition_count);
+    vp9_copy(cm->fc.intra_inter_count, cpi->intra_inter_count);
+    vp9_copy(cm->fc.comp_inter_count, cpi->comp_inter_count);
+    vp9_copy(cm->fc.single_ref_count, cpi->single_ref_count);
+    vp9_copy(cm->fc.comp_ref_count, cpi->comp_ref_count);
     cpi->common.fc.NMVcount = cpi->NMVcount;
     if (!cpi->common.error_resilient_mode &&
         !cpi->common.frame_parallel_decoding_mode) {
diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h
index dece457..b8a60d2 100644
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -47,7 +47,7 @@
 
 #define KEY_FRAME_CONTEXT 5
 
-#define MAX_MODES 41
+#define MAX_MODES 36
 
 #define MIN_THRESHMULT  32
 #define MAX_THRESHMULT  512
@@ -65,29 +65,31 @@
   int nmvcosts_hp[2][MV_VALS];
 
   vp9_prob segment_pred_probs[PREDICTION_PROBS];
-  unsigned char ref_pred_probs_update[PREDICTION_PROBS];
-  vp9_prob ref_pred_probs[PREDICTION_PROBS];
-  vp9_prob prob_comppred[COMP_PRED_CONTEXTS];
+  vp9_prob intra_inter_prob[INTRA_INTER_CONTEXTS];
+  vp9_prob comp_inter_prob[COMP_INTER_CONTEXTS];
+  vp9_prob single_ref_prob[REF_CONTEXTS][2];
+  vp9_prob comp_ref_prob[REF_CONTEXTS];
 
   unsigned char *last_frame_seg_map_copy;
 
   // 0 = Intra, Last, GF, ARF
   signed char last_ref_lf_deltas[MAX_REF_LF_DELTAS];
-  // 0 = I4X4_PRED, ZERO_MV, MV, SPLIT
+  // 0 = ZERO_MV, MV
   signed char last_mode_lf_deltas[MAX_MODE_LF_DELTAS];
 
   vp9_coeff_probs_model coef_probs[TX_SIZE_MAX_SB][BLOCK_TYPES];
 
-  vp9_prob y_mode_prob[VP9_INTRA_MODES - 1]; /* interframe intra mode probs */
+  vp9_prob y_mode_prob[4][VP9_INTRA_MODES - 1];
   vp9_prob uv_mode_prob[VP9_INTRA_MODES][VP9_INTRA_MODES - 1];
-  vp9_prob partition_prob[NUM_PARTITION_CONTEXTS][PARTITION_TYPES - 1];
+  vp9_prob partition_prob[2][NUM_PARTITION_CONTEXTS][PARTITION_TYPES - 1];
 
   vp9_prob switchable_interp_prob[VP9_SWITCHABLE_FILTERS + 1]
                                  [VP9_SWITCHABLE_FILTERS - 1];
 
-  int mv_ref_ct[INTER_MODE_CONTEXTS][VP9_MVREFS - 1][2];
-  int vp9_mode_contexts[INTER_MODE_CONTEXTS][VP9_MVREFS - 1];
+  int inter_mode_counts[INTER_MODE_CONTEXTS][VP9_INTER_MODES - 1][2];
+  vp9_prob inter_mode_probs[INTER_MODE_CONTEXTS][VP9_INTER_MODES - 1];
 
+  vp9_prob tx_probs[TX_SIZE_PROBS];
 } CODING_CONTEXT;
 
 typedef struct {
@@ -174,10 +176,6 @@
 
   THR_B_PRED,
 
-  THR_COMP_ZEROLG,
-  THR_COMP_NEARESTLG,
-  THR_COMP_NEARLG,
-
   THR_COMP_ZEROLA,
   THR_COMP_NEARESTLA,
   THR_COMP_NEARLA,
@@ -186,11 +184,9 @@
   THR_COMP_NEARESTGA,
   THR_COMP_NEARGA,
 
-  THR_COMP_NEWLG,
   THR_COMP_NEWLA,
   THR_COMP_NEWGA,
 
-  THR_COMP_SPLITLG,
   THR_COMP_SPLITLA,
   THR_COMP_SPLITGA,
 } THR_MODES;
@@ -213,11 +209,10 @@
   int max_step_search_steps;
   int first_step;
   int optimize_coefficients;
-  int no_skip_block4x4_search;
   int search_best_filter;
-  int mb16_breakout;
   int static_segmentation;
-  int comp_inter_joint_search;
+  int comp_inter_joint_search_thresh;
+  int adpative_rd_thresh;
 } SPEED_FEATURES;
 
 enum BlockSize {
@@ -320,16 +315,19 @@
   unsigned int mode_chosen_counts[MAX_MODES];
 
   int rd_thresh_mult[MAX_MODES];
-  int rd_baseline_thresh[MAX_MODES];
-  int rd_threshes[MAX_MODES];
+  int rd_baseline_thresh[BLOCK_SIZE_TYPES][MAX_MODES];
+  int rd_threshes[BLOCK_SIZE_TYPES][MAX_MODES];
+  int rd_thresh_freq_fact[BLOCK_SIZE_TYPES][MAX_MODES];
+
   int64_t rd_comp_pred_diff[NB_PREDICTION_TYPES];
   int rd_prediction_type_threshes[4][NB_PREDICTION_TYPES];
-  int comp_pred_count[COMP_PRED_CONTEXTS];
-  int single_pred_count[COMP_PRED_CONTEXTS];
+  unsigned int intra_inter_count[INTRA_INTER_CONTEXTS][2];
+  unsigned int comp_inter_count[COMP_INTER_CONTEXTS][2];
+  unsigned int single_ref_count[REF_CONTEXTS][2][2];
+  unsigned int comp_ref_count[REF_CONTEXTS][2];
+
   // FIXME contextualize
-  int txfm_count_32x32p[TX_SIZE_MAX_SB];
-  int txfm_count_16x16p[TX_SIZE_MAX_SB - 1];
-  int txfm_count_8x8p[TX_SIZE_MAX_SB - 2];
+
   int64_t rd_tx_select_diff[NB_TXFM_MODES];
   int rd_tx_select_threshes[4][NB_TXFM_MODES];
 
@@ -405,7 +403,7 @@
 
   int cq_target_quality;
 
-  int y_mode_count[VP9_INTRA_MODES];
+  int y_mode_count[4][VP9_INTRA_MODES];
   int y_uv_mode_count[VP9_INTRA_MODES][VP9_INTRA_MODES];
   unsigned int partition_count[NUM_PARTITION_CONTEXTS][PARTITION_TYPES];
 
@@ -432,7 +430,6 @@
   int mbgraph_n_frames;             // number of frames filled in the above
   int static_mb_pct;                // % forced skip mbs by segmentation
   int seg0_progress, seg0_idx, seg0_cnt;
-  int ref_pred_count[3][2];
 
   int decimation_factor;
   int decimation_count;
@@ -453,12 +450,8 @@
   vp9_prob last_skip_false_probs[3][MBSKIP_CONTEXTS];
   int last_skip_probs_q[3];
 
-  int recent_ref_frame_usage[MAX_REF_FRAMES];
-  int count_mb_ref_frame_usage[MAX_REF_FRAMES];
   int ref_frame_flags;
 
-  unsigned char ref_pred_probs_update[PREDICTION_PROBS];
-
   SPEED_FEATURES sf;
   int error_bins[1024];
 
@@ -597,7 +590,7 @@
 #endif
 
 #ifdef ENTROPY_STATS
-  int64_t mv_ref_stats[INTER_MODE_CONTEXTS][VP9_MVREFS - 1][2];
+  int64_t mv_ref_stats[INTER_MODE_CONTEXTS][VP9_INTER_MODES - 1][2];
 #endif
 } VP9_COMP;
 
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index 748c3a8..60ca355 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -122,16 +122,18 @@
   vp9_copy(cc->nmvcosts,  cpi->mb.nmvcosts);
   vp9_copy(cc->nmvcosts_hp,  cpi->mb.nmvcosts_hp);
 
-  vp9_copy(cc->vp9_mode_contexts, cm->fc.vp9_mode_contexts);
+  vp9_copy(cc->inter_mode_probs, cm->fc.inter_mode_probs);
 
   vp9_copy(cc->y_mode_prob, cm->fc.y_mode_prob);
   vp9_copy(cc->uv_mode_prob, cm->fc.uv_mode_prob);
   vp9_copy(cc->partition_prob, cm->fc.partition_prob);
 
   vp9_copy(cc->segment_pred_probs, cm->segment_pred_probs);
-  vp9_copy(cc->ref_pred_probs_update, cpi->ref_pred_probs_update);
-  vp9_copy(cc->ref_pred_probs, cm->ref_pred_probs);
-  vp9_copy(cc->prob_comppred, cm->prob_comppred);
+
+  vp9_copy(cc->intra_inter_prob, cm->fc.intra_inter_prob);
+  vp9_copy(cc->comp_inter_prob, cm->fc.comp_inter_prob);
+  vp9_copy(cc->single_ref_prob, cm->fc.single_ref_prob);
+  vp9_copy(cc->comp_ref_prob, cm->fc.comp_ref_prob);
 
   vpx_memcpy(cpi->coding_context.last_frame_seg_map_copy,
              cm->last_frame_seg_map, (cm->mi_rows * cm->mi_cols));
@@ -141,6 +143,7 @@
 
   vp9_copy(cc->coef_probs, cm->fc.coef_probs);
   vp9_copy(cc->switchable_interp_prob, cm->fc.switchable_interp_prob);
+  vp9_copy(cc->tx_probs, cm->fc.tx_probs);
 }
 
 void vp9_restore_coding_context(VP9_COMP *cpi) {
@@ -156,16 +159,18 @@
   vp9_copy(cpi->mb.nmvcosts, cc->nmvcosts);
   vp9_copy(cpi->mb.nmvcosts_hp, cc->nmvcosts_hp);
 
-  vp9_copy(cm->fc.vp9_mode_contexts, cc->vp9_mode_contexts);
+  vp9_copy(cm->fc.inter_mode_probs, cc->inter_mode_probs);
 
   vp9_copy(cm->fc.y_mode_prob, cc->y_mode_prob);
   vp9_copy(cm->fc.uv_mode_prob, cc->uv_mode_prob);
   vp9_copy(cm->fc.partition_prob, cc->partition_prob);
 
   vp9_copy(cm->segment_pred_probs, cc->segment_pred_probs);
-  vp9_copy(cpi->ref_pred_probs_update, cc->ref_pred_probs_update);
-  vp9_copy(cm->ref_pred_probs, cc->ref_pred_probs);
-  vp9_copy(cm->prob_comppred, cc->prob_comppred);
+
+  vp9_copy(cm->fc.intra_inter_prob, cc->intra_inter_prob);
+  vp9_copy(cm->fc.comp_inter_prob, cc->comp_inter_prob);
+  vp9_copy(cm->fc.single_ref_prob, cc->single_ref_prob);
+  vp9_copy(cm->fc.comp_ref_prob, cc->comp_ref_prob);
 
   vpx_memcpy(cm->last_frame_seg_map,
              cpi->coding_context.last_frame_seg_map_copy,
@@ -176,6 +181,7 @@
 
   vp9_copy(cm->fc.coef_probs, cc->coef_probs);
   vp9_copy(cm->fc.switchable_interp_prob, cc->switchable_interp_prob);
+  vp9_copy(cm->fc.tx_probs, cc->tx_probs);
 }
 
 void vp9_setup_key_frame(VP9_COMP *cpi) {
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index aead60b..0fea2b9 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -90,27 +90,32 @@
   {I4X4_PRED, INTRA_FRAME,  NONE},
 
   /* compound prediction modes */
-  {ZEROMV,    LAST_FRAME,   GOLDEN_FRAME},
-  {NEARESTMV, LAST_FRAME,   GOLDEN_FRAME},
-  {NEARMV,    LAST_FRAME,   GOLDEN_FRAME},
-
-  {ZEROMV,    ALTREF_FRAME, LAST_FRAME},
-  {NEARESTMV, ALTREF_FRAME, LAST_FRAME},
-  {NEARMV,    ALTREF_FRAME, LAST_FRAME},
+  {ZEROMV,    LAST_FRAME,   ALTREF_FRAME},
+  {NEARESTMV, LAST_FRAME,   ALTREF_FRAME},
+  {NEARMV,    LAST_FRAME,   ALTREF_FRAME},
 
   {ZEROMV,    GOLDEN_FRAME, ALTREF_FRAME},
   {NEARESTMV, GOLDEN_FRAME, ALTREF_FRAME},
   {NEARMV,    GOLDEN_FRAME, ALTREF_FRAME},
 
-  {NEWMV,     LAST_FRAME,   GOLDEN_FRAME},
-  {NEWMV,     ALTREF_FRAME, LAST_FRAME  },
+  {NEWMV,     LAST_FRAME,   ALTREF_FRAME},
   {NEWMV,     GOLDEN_FRAME, ALTREF_FRAME},
 
-  {SPLITMV,   LAST_FRAME,   GOLDEN_FRAME},
-  {SPLITMV,   ALTREF_FRAME, LAST_FRAME  },
+  {SPLITMV,   LAST_FRAME,   ALTREF_FRAME},
   {SPLITMV,   GOLDEN_FRAME, ALTREF_FRAME},
 };
 
+// The baseline rd thresholds for breaking out of the rd loop for
+// certain modes are assumed to be based on 8x8 blocks.
+// This table is used to correct for blocks size.
+// The factors here are << 2 (2 = x0.5, 32 = x8 etc).
+static int rd_thresh_block_size_factor[BLOCK_SIZE_TYPES] =
+  {2, 3, 3, 4, 6, 6, 8, 12, 12, 16, 24, 24, 32};
+
+#define BASE_RD_THRESH_FREQ_FACT 16
+#define MAX_RD_THRESH_FREQ_FACT 32
+#define MAX_RD_THRESH_FREQ_INC 1
+
 static void fill_token_costs(vp9_coeff_count (*c)[BLOCK_TYPES],
                              vp9_coeff_count (*cnoskip)[BLOCK_TYPES],
                              vp9_coeff_probs_model (*p)[BLOCK_TYPES]) {
@@ -175,7 +180,7 @@
 
 
 void vp9_initialize_rd_consts(VP9_COMP *cpi, int qindex) {
-  int q, i;
+  int q, i, bsize;
 
   vp9_clear_system_state();  // __asm emms;
 
@@ -207,24 +212,43 @@
     cpi->RDDIV = 1;
     cpi->RDMULT /= 100;
 
-    for (i = 0; i < MAX_MODES; i++) {
-      if (cpi->sf.thresh_mult[i] < INT_MAX) {
-        cpi->rd_threshes[i] = cpi->sf.thresh_mult[i] * q / 100;
-      } else {
-        cpi->rd_threshes[i] = INT_MAX;
+    for (bsize = 0; bsize < BLOCK_SIZE_TYPES; ++bsize) {
+      for (i = 0; i < MAX_MODES; ++i) {
+        // Threshold here seem unecessarily harsh but fine given actual
+        // range of values used for cpi->sf.thresh_mult[]
+        int thresh_max = INT_MAX / (q * rd_thresh_block_size_factor[bsize]);
+
+        // *4 relates to the scaling of rd_thresh_block_size_factor[]
+        if ((int64_t)cpi->sf.thresh_mult[i] < thresh_max) {
+          cpi->rd_threshes[bsize][i] =
+            cpi->sf.thresh_mult[i] * q *
+            rd_thresh_block_size_factor[bsize] / (4 * 100);
+        } else {
+          cpi->rd_threshes[bsize][i] = INT_MAX;
+        }
+        cpi->rd_baseline_thresh[bsize][i] = cpi->rd_threshes[bsize][i];
+        cpi->rd_thresh_freq_fact[bsize][i] = BASE_RD_THRESH_FREQ_FACT;
       }
-      cpi->rd_baseline_thresh[i] = cpi->rd_threshes[i];
     }
   } else {
     cpi->RDDIV = 100;
 
-    for (i = 0; i < MAX_MODES; i++) {
-      if (cpi->sf.thresh_mult[i] < (INT_MAX / q)) {
-        cpi->rd_threshes[i] = cpi->sf.thresh_mult[i] * q;
-      } else {
-        cpi->rd_threshes[i] = INT_MAX;
+    for (bsize = 0; bsize < BLOCK_SIZE_TYPES; ++bsize) {
+      for (i = 0; i < MAX_MODES; i++) {
+        // Threshold here seem unecessarily harsh but fine given actual
+        // range of values used for cpi->sf.thresh_mult[]
+        int thresh_max = INT_MAX / (q * rd_thresh_block_size_factor[bsize]);
+
+        if (cpi->sf.thresh_mult[i] < thresh_max) {
+          cpi->rd_threshes[bsize][i] =
+            cpi->sf.thresh_mult[i] * q *
+            rd_thresh_block_size_factor[bsize] / 4;
+        } else {
+          cpi->rd_threshes[bsize][i] = INT_MAX;
+        }
+        cpi->rd_baseline_thresh[bsize][i] = cpi->rd_threshes[bsize][i];
+        cpi->rd_thresh_freq_fact[bsize][i] = BASE_RD_THRESH_FREQ_FACT;
       }
-      cpi->rd_baseline_thresh[i] = cpi->rd_threshes[i];
     }
   }
 
@@ -234,7 +258,7 @@
 
   for (i = 0; i < NUM_PARTITION_CONTEXTS; i++)
     vp9_cost_tokens(cpi->mb.partition_cost[i],
-                    cpi->common.fc.partition_prob[i],
+                    cpi->common.fc.partition_prob[cpi->common.frame_type][i],
                     vp9_partition_tree);
 
   /*rough estimate for costing*/
@@ -276,7 +300,7 @@
   const int eob = xd->plane[plane].eobs[block];
   const int16_t *qcoeff_ptr = BLOCK_OFFSET(xd->plane[plane].qcoeff,
                                            block, 16);
-  const int ref = mbmi->ref_frame != INTRA_FRAME;
+  const int ref = mbmi->ref_frame[0] != INTRA_FRAME;
   unsigned int (*token_costs)[PREV_COEF_CONTEXTS][MAX_ENTROPY_TOKENS] =
       mb->token_costs[tx_size][type][ref];
   ENTROPY_CONTEXT above_ec, left_ec;
@@ -396,6 +420,7 @@
                                      int *d, int *distortion,
                                      int *s, int *skip,
                                      int64_t txfm_cache[NB_TXFM_MODES],
+                                     BLOCK_SIZE_TYPE bs,
                                      TX_SIZE max_txfm_size) {
   VP9_COMMON *const cm = &cpi->common;
   MACROBLOCKD *const xd = &x->e_mbd;
@@ -405,13 +430,15 @@
   int n, m;
   int s0, s1;
 
+  int tx_probs_offset = get_tx_probs_offset(bs);
+
   for (n = TX_4X4; n <= max_txfm_size; n++) {
     r[n][1] = r[n][0];
     for (m = 0; m <= n - (n == max_txfm_size); m++) {
       if (m == n)
-        r[n][1] += vp9_cost_zero(cm->prob_tx[m]);
+        r[n][1] += vp9_cost_zero(cm->fc.tx_probs[tx_probs_offset + m]);
       else
-        r[n][1] += vp9_cost_one(cm->prob_tx[m]);
+        r[n][1] += vp9_cost_one(cm->fc.tx_probs[tx_probs_offset + m]);
     }
   }
 
@@ -505,33 +532,48 @@
   return sum > INT_MAX ? INT_MAX : (int)sum;
 }
 
-static int rdcost_plane(VP9_COMMON *const cm, MACROBLOCK *x,
-                        int plane, BLOCK_SIZE_TYPE bsize, TX_SIZE tx_size) {
-  MACROBLOCKD *const xd = &x->e_mbd;
+struct rdcost_block_args {
+  VP9_COMMON *cm;
+  MACROBLOCK *x;
+  ENTROPY_CONTEXT t_above[16];
+  ENTROPY_CONTEXT t_left[16];
+  TX_SIZE tx_size;
+  int bw;
+  int bh;
+  int cost;
+};
+
+static void rdcost_block(int plane, int block, BLOCK_SIZE_TYPE bsize,
+                         int ss_txfrm_size, void *arg) {
+  struct rdcost_block_args* args = arg;
+  int x_idx, y_idx;
+  MACROBLOCKD * const xd = &args->x->e_mbd;
+
+  txfrm_block_to_raster_xy(xd, bsize, plane, block, args->tx_size * 2, &x_idx,
+                           &y_idx);
+
+  args->cost += cost_coeffs(args->cm, args->x, plane, block,
+                            xd->plane[plane].plane_type, args->t_above + x_idx,
+                            args->t_left + y_idx, args->tx_size,
+                            args->bw * args->bh);
+}
+
+static int rdcost_plane(VP9_COMMON * const cm, MACROBLOCK *x, int plane,
+                        BLOCK_SIZE_TYPE bsize, TX_SIZE tx_size) {
+  MACROBLOCKD * const xd = &x->e_mbd;
   const int bwl = b_width_log2(bsize) - xd->plane[plane].subsampling_x;
   const int bhl = b_height_log2(bsize) - xd->plane[plane].subsampling_y;
   const int bw = 1 << bwl, bh = 1 << bhl;
-  ENTROPY_CONTEXT t_above[16], t_left[16];
-  int block, cost;
+  struct rdcost_block_args args = { cm, x, { 0 }, { 0 }, tx_size, bw, bh, 0 };
 
-  vpx_memcpy(&t_above, xd->plane[plane].above_context,
+  vpx_memcpy(&args.t_above, xd->plane[plane].above_context,
              sizeof(ENTROPY_CONTEXT) * bw);
-  vpx_memcpy(&t_left,  xd->plane[plane].left_context,
+  vpx_memcpy(&args.t_left, xd->plane[plane].left_context,
              sizeof(ENTROPY_CONTEXT) * bh);
 
-  cost = 0;
-  for (block = 0; block < bw * bh; block += 1 << (tx_size * 2)) {
-    int x_idx, y_idx;
+  foreach_transformed_block_in_plane(xd, bsize, plane, rdcost_block, &args);
 
-    txfrm_block_to_raster_xy(xd, bsize, plane, block, tx_size * 2,
-                             &x_idx, &y_idx);
-
-    cost += cost_coeffs(cm, x, plane, block, xd->plane[plane].plane_type,
-                        t_above + x_idx, t_left + y_idx,
-                        tx_size, bw * bh);
-  }
-
-  return cost;
+  return args.cost;
 }
 
 static int rdcost_uv(VP9_COMMON *const cm, MACROBLOCK *x,
@@ -549,7 +591,11 @@
                                      BLOCK_SIZE_TYPE bsize, TX_SIZE tx_size) {
   MACROBLOCKD *const xd = &x->e_mbd;
   xd->mode_info_context->mbmi.txfm_size = tx_size;
-  vp9_xform_quant_sby(cm, x, bsize);
+
+  if (xd->mode_info_context->mbmi.ref_frame[0] == INTRA_FRAME)
+    vp9_encode_intra_block_y(cm, x, bsize);
+  else
+    vp9_xform_quant_sby(cm, x, bsize);
 
   *distortion = block_error_sby(x, bsize, tx_size == TX_32X32 ? 0 : 2);
   *rate       = rdcost_plane(cm, x, 0, bsize, tx_size);
@@ -565,7 +611,10 @@
   MACROBLOCKD *xd = &x->e_mbd;
   MB_MODE_INFO *const mbmi = &xd->mode_info_context->mbmi;
 
-  vp9_subtract_sby(x, bs);
+  assert(bs == mbmi->sb_type);
+
+  if (mbmi->ref_frame[0] > INTRA_FRAME)
+    vp9_subtract_sby(x, bs);
 
   if (cpi->speed > 4) {
     if (bs >= BLOCK_SIZE_SB32X32) {
@@ -577,6 +626,7 @@
     } else {
       mbmi->txfm_size = TX_4X4;
     }
+    vpx_memset(txfm_cache, 0, NB_TXFM_MODES * sizeof(int64_t));
     super_block_yrd_for_txfm(cm, x, rate, distortion, skip, bs,
                              mbmi->txfm_size);
     return;
@@ -592,7 +642,8 @@
   super_block_yrd_for_txfm(cm, x, &r[TX_4X4][0], &d[TX_4X4], &s[TX_4X4], bs,
                            TX_4X4);
 
-  choose_txfm_size_from_rd(cpi, x, r, rate, d, distortion, s, skip, txfm_cache,
+  choose_txfm_size_from_rd(cpi, x, r, rate, d, distortion, s,
+                           skip, txfm_cache, bs,
                            TX_32X32 - (bs < BLOCK_SIZE_SB32X32)
                            - (bs < BLOCK_SIZE_MB16X16));
 }
@@ -821,6 +872,7 @@
     int64_t local_txfm_cache[NB_TXFM_MODES];
     MODE_INFO *const mic = xd->mode_info_context;
     const int mis = xd->mode_info_stride;
+
     if (cpi->common.frame_type == KEY_FRAME) {
       const MB_PREDICTION_MODE A = above_block_mode(mic, 0, mis);
       const MB_PREDICTION_MODE L = xd->left_available ?
@@ -829,7 +881,6 @@
       bmode_costs = x->y_mode_costs[A][L];
     }
     x->e_mbd.mode_info_context->mbmi.mode = mode;
-    vp9_build_intra_predictors_sby_s(&x->e_mbd, bsize);
 
     super_block_yrd(cpi, x, &this_rate_tokenonly, &this_distortion, &s,
                     bsize, local_txfm_cache);
@@ -867,7 +918,10 @@
                                       int *skippable, BLOCK_SIZE_TYPE bsize,
                                       TX_SIZE uv_tx_size) {
   MACROBLOCKD *const xd = &x->e_mbd;
-  vp9_xform_quant_sbuv(cm, x, bsize);
+  if (xd->mode_info_context->mbmi.ref_frame[0] == INTRA_FRAME)
+    vp9_encode_intra_block_uv(cm, x, bsize);
+  else
+    vp9_xform_quant_sbuv(cm, x, bsize);
 
   *distortion = block_error_sbuv(x, bsize, uv_tx_size == TX_32X32 ? 0 : 2);
   *rate       = rdcost_uv(cm, x, bsize, uv_tx_size);
@@ -880,7 +934,8 @@
   MACROBLOCKD *const xd = &x->e_mbd;
   MB_MODE_INFO *const mbmi = &xd->mode_info_context->mbmi;
 
-  vp9_subtract_sbuv(x, bsize);
+  if (mbmi->ref_frame[0] > INTRA_FRAME)
+    vp9_subtract_sbuv(x, bsize);
 
   if (mbmi->txfm_size >= TX_32X32 && bsize >= BLOCK_SIZE_SB64X64) {
     super_block_uvrd_for_txfm(cm, x, rate, distortion, skippable, bsize,
@@ -909,8 +964,6 @@
 
   for (mode = DC_PRED; mode <= TM_PRED; mode++) {
     x->e_mbd.mode_info_context->mbmi.uv_mode = mode;
-    vp9_build_intra_predictors_sbuv_s(&x->e_mbd, bsize);
-
     super_block_uvrd(&cpi->common, x, &this_rate_tokenonly,
                      &this_distortion, &s, bsize);
     this_rate = this_rate_tokenonly +
@@ -942,7 +995,7 @@
   if (!vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP)) {
     VP9_COMMON *pc = &cpi->common;
 
-    vp9_prob p [VP9_MVREFS - 1];
+    vp9_prob p[VP9_INTER_MODES - 1];
     assert(NEARESTMV <= m  &&  m <= NEWMV);
     vp9_mv_ref_probs(pc, p, mode_context);
     return cost_token(vp9_sb_mv_ref_tree, p,
@@ -981,31 +1034,31 @@
   // is when we are on a new label  (jbb May 08, 2007)
   switch (m = this_mode) {
     case NEWMV:
-      this_mv->as_int = seg_mvs[mbmi->ref_frame].as_int;
+      this_mv->as_int = seg_mvs[mbmi->ref_frame[0]].as_int;
       thismvcost  = vp9_mv_bit_cost(this_mv, best_ref_mv, mvjcost, mvcost,
                                     102, xd->allow_high_precision_mv);
-      if (mbmi->second_ref_frame > 0) {
-        this_second_mv->as_int = seg_mvs[mbmi->second_ref_frame].as_int;
+      if (mbmi->ref_frame[1] > 0) {
+        this_second_mv->as_int = seg_mvs[mbmi->ref_frame[1]].as_int;
         thismvcost += vp9_mv_bit_cost(this_second_mv, second_best_ref_mv,
                                       mvjcost, mvcost, 102,
                                       xd->allow_high_precision_mv);
       }
       break;
     case NEARESTMV:
-      this_mv->as_int = frame_mv[NEARESTMV][mbmi->ref_frame].as_int;
-      if (mbmi->second_ref_frame > 0)
+      this_mv->as_int = frame_mv[NEARESTMV][mbmi->ref_frame[0]].as_int;
+      if (mbmi->ref_frame[1] > 0)
         this_second_mv->as_int =
-            frame_mv[NEARESTMV][mbmi->second_ref_frame].as_int;
+            frame_mv[NEARESTMV][mbmi->ref_frame[1]].as_int;
       break;
     case NEARMV:
-      this_mv->as_int = frame_mv[NEARMV][mbmi->ref_frame].as_int;
-      if (mbmi->second_ref_frame > 0)
+      this_mv->as_int = frame_mv[NEARMV][mbmi->ref_frame[0]].as_int;
+      if (mbmi->ref_frame[1] > 0)
         this_second_mv->as_int =
-            frame_mv[NEARMV][mbmi->second_ref_frame].as_int;
+            frame_mv[NEARMV][mbmi->ref_frame[1]].as_int;
       break;
     case ZEROMV:
       this_mv->as_int = 0;
-      if (mbmi->second_ref_frame > 0)
+      if (mbmi->ref_frame[1] > 0)
         this_second_mv->as_int = 0;
       break;
     default:
@@ -1013,15 +1066,15 @@
   }
 
   cost = vp9_cost_mv_ref(cpi, this_mode,
-                         mbmi->mb_mode_context[mbmi->ref_frame]);
+                         mbmi->mb_mode_context[mbmi->ref_frame[0]]);
 
   mic->bmi[i].as_mv[0].as_int = this_mv->as_int;
-  if (mbmi->second_ref_frame > 0)
+  if (mbmi->ref_frame[1] > 0)
     mic->bmi[i].as_mv[1].as_int = this_second_mv->as_int;
 
   x->partition_info->bmi[i].mode = m;
   x->partition_info->bmi[i].mv.as_int = this_mv->as_int;
-  if (mbmi->second_ref_frame > 0)
+  if (mbmi->ref_frame[1] > 0)
     x->partition_info->bmi[i].second_mv.as_int = this_second_mv->as_int;
   for (idy = 0; idy < bh; ++idy) {
     for (idx = 0; idx < bw; ++idx) {
@@ -1083,7 +1136,7 @@
   // TODO(debargha): Make this work properly with the
   // implicit-compoundinter-weight experiment when implicit
   // weighting for splitmv modes is turned on.
-  if (xd->mode_info_context->mbmi.second_ref_frame > 0) {
+  if (xd->mode_info_context->mbmi.ref_frame[1] > 0) {
     uint8_t* const second_pre =
     raster_block_offset_uint8(xd, BLOCK_SIZE_SB8X8, 0, i,
                               xd->plane[0].pre[1].buf,
@@ -1201,7 +1254,7 @@
       raster_block_offset_uint8(&x->e_mbd, BLOCK_SIZE_SB8X8, 0, i,
                                 x->e_mbd.plane[0].pre[0].buf,
                                 x->e_mbd.plane[0].pre[0].stride);
-  if (mbmi->second_ref_frame)
+  if (mbmi->ref_frame[1])
     x->e_mbd.plane[0].pre[1].buf =
         raster_block_offset_uint8(&x->e_mbd, BLOCK_SIZE_SB8X8, 0, i,
                                   x->e_mbd.plane[0].pre[1].buf,
@@ -1213,7 +1266,7 @@
   MB_MODE_INFO *mbmi = &x->e_mbd.mode_info_context->mbmi;
   x->plane[0].src = orig_src;
   x->e_mbd.plane[0].pre[0] = orig_pre[0];
-  if (mbmi->second_ref_frame)
+  if (mbmi->ref_frame[1])
     x->e_mbd.plane[0].pre[1] = orig_pre[1];
 }
 
@@ -1273,16 +1326,16 @@
       int bestlabelyrate = 0;
       i = idy * 2 + idx;
 
-      frame_mv[ZEROMV][mbmi->ref_frame].as_int = 0;
-      frame_mv[ZEROMV][mbmi->second_ref_frame].as_int = 0;
+      frame_mv[ZEROMV][mbmi->ref_frame[0]].as_int = 0;
+      frame_mv[ZEROMV][mbmi->ref_frame[1]].as_int = 0;
       vp9_append_sub8x8_mvs_for_idx(&cpi->common, &x->e_mbd,
-                                    &frame_mv[NEARESTMV][mbmi->ref_frame],
-                                    &frame_mv[NEARMV][mbmi->ref_frame],
+                                    &frame_mv[NEARESTMV][mbmi->ref_frame[0]],
+                                    &frame_mv[NEARMV][mbmi->ref_frame[0]],
                                     i, 0);
-      if (mbmi->second_ref_frame > 0)
+      if (mbmi->ref_frame[1] > 0)
         vp9_append_sub8x8_mvs_for_idx(&cpi->common, &x->e_mbd,
-                                   &frame_mv[NEARESTMV][mbmi->second_ref_frame],
-                                   &frame_mv[NEARMV][mbmi->second_ref_frame],
+                                   &frame_mv[NEARESTMV][mbmi->ref_frame[1]],
+                                   &frame_mv[NEARMV][mbmi->ref_frame[1]],
                                    i, 1);
 
       // search for the best motion vector on this segment
@@ -1300,7 +1353,7 @@
         vpx_memcpy(t_left_s, t_left, sizeof(t_left_s));
 
         // motion search for newmv (single predictor case only)
-        if (mbmi->second_ref_frame <= 0 && this_mode == NEWMV) {
+        if (mbmi->ref_frame[1] <= 0 && this_mode == NEWMV) {
           int step_param = 0;
           int further_steps;
           int thissme, bestsme = INT_MAX;
@@ -1367,26 +1420,26 @@
                                          &distortion, &sse);
 
             // safe motion search result for use in compound prediction
-            seg_mvs[i][mbmi->ref_frame].as_int = mode_mv[NEWMV].as_int;
+            seg_mvs[i][mbmi->ref_frame[0]].as_int = mode_mv[NEWMV].as_int;
           }
 
           // restore src pointers
           mi_buf_restore(x, orig_src, orig_pre);
-        } else if (mbmi->second_ref_frame > 0 && this_mode == NEWMV) {
-          if (seg_mvs[i][mbmi->second_ref_frame].as_int == INVALID_MV ||
-              seg_mvs[i][mbmi->ref_frame       ].as_int == INVALID_MV)
+        } else if (mbmi->ref_frame[1] > 0 && this_mode == NEWMV) {
+          if (seg_mvs[i][mbmi->ref_frame[1]].as_int == INVALID_MV ||
+              seg_mvs[i][mbmi->ref_frame[0]].as_int == INVALID_MV)
             continue;
 
           // adjust src pointers
           mi_buf_shift(x, i);
-          if (cpi->compressor_speed == 0 && cpi->sf.comp_inter_joint_search) {
+          if (cpi->sf.comp_inter_joint_search_thresh < bsize) {
             iterative_motion_search(cpi, x, bsize, frame_mv[this_mode],
                                     scaled_ref_frame,
                                     mi_row, mi_col, seg_mvs[i]);
-            seg_mvs[i][mbmi->ref_frame].as_int =
-                frame_mv[this_mode][mbmi->ref_frame].as_int;
-            seg_mvs[i][mbmi->second_ref_frame].as_int =
-                frame_mv[this_mode][mbmi->second_ref_frame].as_int;
+            seg_mvs[i][mbmi->ref_frame[0]].as_int =
+                frame_mv[this_mode][mbmi->ref_frame[0]].as_int;
+            seg_mvs[i][mbmi->ref_frame[1]].as_int =
+                frame_mv[this_mode][mbmi->ref_frame[1]].as_int;
           }
           // restore src pointers
           mi_buf_restore(x, orig_src, orig_pre);
@@ -1404,7 +1457,7 @@
             ((mode_mv[this_mode].as_mv.col >> 3) > x->mv_col_max)) {
           continue;
         }
-        if (mbmi->second_ref_frame > 0 &&
+        if (mbmi->ref_frame[1] > 0 &&
             mv_check_bounds(x, &second_mode_mv[this_mode]))
           continue;
 
@@ -1460,7 +1513,7 @@
     // store everything needed to come back to this!!
     for (i = 0; i < 4; i++) {
       bsi->mvs[i].as_mv = x->partition_info->bmi[i].mv.as_mv;
-      if (mbmi->second_ref_frame > 0)
+      if (mbmi->ref_frame[1] > 0)
         bsi->second_mvs[i].as_mv = x->partition_info->bmi[i].second_mv.as_mv;
       bsi->modes[i] = x->partition_info->bmi[i].mode;
       bsi->eobs[i] = best_eobs[i];
@@ -1498,7 +1551,7 @@
   /* set it to the best */
   for (i = 0; i < 4; i++) {
     x->e_mbd.mode_info_context->bmi[i].as_mv[0].as_int = bsi.mvs[i].as_int;
-    if (mbmi->second_ref_frame > 0)
+    if (mbmi->ref_frame[1] > 0)
       x->e_mbd.mode_info_context->bmi[i].as_mv[1].as_int =
       bsi.second_mvs[i].as_int;
     x->e_mbd.plane[0].eobs[i] = bsi.eobs[i];
@@ -1510,14 +1563,14 @@
   for (i = 0; i < x->partition_info->count; i++) {
     x->partition_info->bmi[i].mode = bsi.modes[i];
     x->partition_info->bmi[i].mv.as_mv = bsi.mvs[i].as_mv;
-    if (mbmi->second_ref_frame > 0)
+    if (mbmi->ref_frame[1] > 0)
       x->partition_info->bmi[i].second_mv.as_mv = bsi.second_mvs[i].as_mv;
   }
   /*
    * used to set mbmi->mv.as_int
    */
   x->partition_info->bmi[3].mv.as_int = bsi.mvs[3].as_int;
-  if (mbmi->second_ref_frame > 0)
+  if (mbmi->ref_frame[1] > 0)
     x->partition_info->bmi[3].second_mv.as_int = bsi.second_mvs[3].as_int;
 
   *returntotrate = bsi.r;
@@ -1574,77 +1627,15 @@
   x->mv_best_ref_index[ref_frame] = best_index;
 }
 
-extern void vp9_calc_ref_probs(int *count, vp9_prob *probs);
-static void estimate_curframe_refprobs(VP9_COMP *cpi,
-                                       vp9_prob mod_refprobs[3],
-                                       int pred_ref) {
-  int norm_cnt[MAX_REF_FRAMES];
-  const int *const rfct = cpi->count_mb_ref_frame_usage;
-  int intra_count = rfct[INTRA_FRAME];
-  int last_count  = rfct[LAST_FRAME];
-  int gf_count    = rfct[GOLDEN_FRAME];
-  int arf_count   = rfct[ALTREF_FRAME];
-
-  // Work out modified reference frame probabilities to use where prediction
-  // of the reference frame fails
-  if (pred_ref == INTRA_FRAME) {
-    norm_cnt[0] = 0;
-    norm_cnt[1] = last_count;
-    norm_cnt[2] = gf_count;
-    norm_cnt[3] = arf_count;
-    vp9_calc_ref_probs(norm_cnt, mod_refprobs);
-    mod_refprobs[0] = 0;    // This branch implicit
-  } else if (pred_ref == LAST_FRAME) {
-    norm_cnt[0] = intra_count;
-    norm_cnt[1] = 0;
-    norm_cnt[2] = gf_count;
-    norm_cnt[3] = arf_count;
-    vp9_calc_ref_probs(norm_cnt, mod_refprobs);
-    mod_refprobs[1] = 0;    // This branch implicit
-  } else if (pred_ref == GOLDEN_FRAME) {
-    norm_cnt[0] = intra_count;
-    norm_cnt[1] = last_count;
-    norm_cnt[2] = 0;
-    norm_cnt[3] = arf_count;
-    vp9_calc_ref_probs(norm_cnt, mod_refprobs);
-    mod_refprobs[2] = 0;  // This branch implicit
-  } else {
-    norm_cnt[0] = intra_count;
-    norm_cnt[1] = last_count;
-    norm_cnt[2] = gf_count;
-    norm_cnt[3] = 0;
-    vp9_calc_ref_probs(norm_cnt, mod_refprobs);
-    mod_refprobs[2] = 0;  // This branch implicit
-  }
-}
-
-static INLINE unsigned weighted_cost(vp9_prob *tab0, vp9_prob *tab1,
-                                     int idx, int val, int weight) {
-  unsigned cost0 = tab0[idx] ? vp9_cost_bit(tab0[idx], val) : 0;
-  unsigned cost1 = tab1[idx] ? vp9_cost_bit(tab1[idx], val) : 0;
-  // weight is 16-bit fixed point, so this basically calculates:
-  // 0.5 + weight * cost1 + (1.0 - weight) * cost0
-  return (0x8000 + weight * cost1 + (0x10000 - weight) * cost0) >> 16;
-}
-
 static void estimate_ref_frame_costs(VP9_COMP *cpi, int segment_id,
-                                     unsigned int *ref_costs) {
-  VP9_COMMON *cm = &cpi->common;
-  MACROBLOCKD *xd = &cpi->mb.e_mbd;
-  vp9_prob *mod_refprobs;
-
-  unsigned int cost;
-  int pred_ref;
-  int pred_flag;
-  int pred_ctx;
-  int i;
-
-  vp9_prob pred_prob, new_pred_prob;
-  int seg_ref_active;
+                                     unsigned int *ref_costs_single,
+                                     unsigned int *ref_costs_comp,
+                                     vp9_prob *comp_mode_p) {
+  VP9_COMMON *const cm = &cpi->common;
+  MACROBLOCKD *const xd = &cpi->mb.e_mbd;
+  int seg_ref_active = vp9_segfeature_active(xd, segment_id,
+                                             SEG_LVL_REF_FRAME);
   int seg_ref_count = 0;
-  seg_ref_active = vp9_segfeature_active(xd,
-                                         segment_id,
-                                         SEG_LVL_REF_FRAME);
 
   if (seg_ref_active) {
     seg_ref_count = vp9_check_segref(xd, segment_id, INTRA_FRAME)  +
@@ -1653,56 +1644,56 @@
                     vp9_check_segref(xd, segment_id, ALTREF_FRAME);
   }
 
-  // Get the predicted reference for this mb
-  pred_ref = vp9_get_pred_ref(cm, xd);
+  if (seg_ref_active && seg_ref_count == 1) {
+    vpx_memset(ref_costs_single, 0, MAX_REF_FRAMES * sizeof(*ref_costs_single));
+    vpx_memset(ref_costs_comp,   0, MAX_REF_FRAMES * sizeof(*ref_costs_comp));
+    *comp_mode_p = 128;
+  } else {
+    vp9_prob intra_inter_p = vp9_get_pred_prob(cm, xd, PRED_INTRA_INTER);
+    vp9_prob comp_inter_p = 128;
 
-  // Get the context probability for the prediction flag (based on last frame)
-  pred_prob = vp9_get_pred_prob(cm, xd, PRED_REF);
-
-  // Predict probability for current frame based on stats so far
-  pred_ctx = vp9_get_pred_context(cm, xd, PRED_REF);
-  new_pred_prob = get_binary_prob(cpi->ref_pred_count[pred_ctx][0],
-                                  cpi->ref_pred_count[pred_ctx][1]);
-
-  // Get the set of probabilities to use if prediction fails
-  mod_refprobs = cm->mod_refprobs[pred_ref];
-
-  // For each possible selected reference frame work out a cost.
-  for (i = 0; i < MAX_REF_FRAMES; i++) {
-    if (seg_ref_active && seg_ref_count == 1) {
-      cost = 0;
+    if (cm->comp_pred_mode == HYBRID_PREDICTION) {
+      comp_inter_p = vp9_get_pred_prob(cm, xd, PRED_COMP_INTER_INTER);
+      *comp_mode_p = comp_inter_p;
     } else {
-      pred_flag = (i == pred_ref);
-
-      // Get the prediction for the current mb
-      cost = weighted_cost(&pred_prob, &new_pred_prob, 0,
-                           pred_flag, cpi->seg0_progress);
-      if (cost > 1024) cost = 768;  // i.e. account for 4 bits max.
-
-      // for incorrectly predicted cases
-      if (!pred_flag) {
-        vp9_prob curframe_mod_refprobs[3];
-
-        if (cpi->seg0_progress) {
-          estimate_curframe_refprobs(cpi, curframe_mod_refprobs, pred_ref);
-        } else {
-          vpx_memset(curframe_mod_refprobs, 0, sizeof(curframe_mod_refprobs));
-        }
-
-        cost += weighted_cost(mod_refprobs, curframe_mod_refprobs, 0,
-                              (i != INTRA_FRAME), cpi->seg0_progress);
-        if (i != INTRA_FRAME) {
-          cost += weighted_cost(mod_refprobs, curframe_mod_refprobs, 1,
-                                (i != LAST_FRAME), cpi->seg0_progress);
-          if (i != LAST_FRAME) {
-            cost += weighted_cost(mod_refprobs, curframe_mod_refprobs, 2,
-                                  (i != GOLDEN_FRAME), cpi->seg0_progress);
-          }
-        }
-      }
+      *comp_mode_p = 128;
     }
 
-    ref_costs[i] = cost;
+    ref_costs_single[INTRA_FRAME] = vp9_cost_bit(intra_inter_p, 0);
+
+    if (cm->comp_pred_mode != COMP_PREDICTION_ONLY) {
+      vp9_prob ref_single_p1 = vp9_get_pred_prob(cm, xd, PRED_SINGLE_REF_P1);
+      vp9_prob ref_single_p2 = vp9_get_pred_prob(cm, xd, PRED_SINGLE_REF_P2);
+      unsigned int base_cost = vp9_cost_bit(intra_inter_p, 1);
+
+      if (cm->comp_pred_mode == HYBRID_PREDICTION)
+        base_cost += vp9_cost_bit(comp_inter_p, 0);
+
+      ref_costs_single[LAST_FRAME] = ref_costs_single[GOLDEN_FRAME] =
+          ref_costs_single[ALTREF_FRAME] = base_cost;
+      ref_costs_single[LAST_FRAME]   += vp9_cost_bit(ref_single_p1, 0);
+      ref_costs_single[GOLDEN_FRAME] += vp9_cost_bit(ref_single_p1, 1);
+      ref_costs_single[ALTREF_FRAME] += vp9_cost_bit(ref_single_p1, 1);
+      ref_costs_single[GOLDEN_FRAME] += vp9_cost_bit(ref_single_p2, 0);
+      ref_costs_single[ALTREF_FRAME] += vp9_cost_bit(ref_single_p2, 1);
+    } else {
+      ref_costs_single[LAST_FRAME]   = 512;
+      ref_costs_single[GOLDEN_FRAME] = 512;
+      ref_costs_single[ALTREF_FRAME] = 512;
+    }
+    if (cm->comp_pred_mode != SINGLE_PREDICTION_ONLY) {
+      vp9_prob ref_comp_p = vp9_get_pred_prob(cm, xd, PRED_COMP_REF_P);
+      unsigned int base_cost = vp9_cost_bit(intra_inter_p, 1);
+
+      if (cm->comp_pred_mode == HYBRID_PREDICTION)
+        base_cost += vp9_cost_bit(comp_inter_p, 1);
+
+      ref_costs_comp[LAST_FRAME]   = base_cost + vp9_cost_bit(ref_comp_p, 0);
+      ref_costs_comp[GOLDEN_FRAME] = base_cost + vp9_cost_bit(ref_comp_p, 1);
+    } else {
+      ref_costs_comp[LAST_FRAME]   = 512;
+      ref_costs_comp[GOLDEN_FRAME] = 512;
+    }
   }
 }
 
@@ -1906,8 +1897,8 @@
   int pw = 4 << b_width_log2(bsize), ph = 4 << b_height_log2(bsize);
   MACROBLOCKD *xd = &x->e_mbd;
   MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi;
-  int refs[2] = { mbmi->ref_frame,
-                  (mbmi->second_ref_frame < 0 ? 0 : mbmi->second_ref_frame) };
+  int refs[2] = { mbmi->ref_frame[0],
+                  (mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1]) };
   int_mv ref_mv[2];
   const enum BlockSize block_size = get_plane_block_size(bsize, &xd->plane[0]);
   int ite;
@@ -2049,7 +2040,6 @@
                                  BLOCK_SIZE_TYPE bsize,
                                  int64_t txfm_cache[],
                                  int *rate2, int *distortion, int *skippable,
-                                 int *compmode_cost,
                                  int *rate_y, int *distortion_y,
                                  int *rate_uv, int *distortion_uv,
                                  int *mode_excluded, int *disable_skip,
@@ -2066,12 +2056,12 @@
   const enum BlockSize uv_block_size = get_plane_block_size(bsize,
                                                             &xd->plane[1]);
   MB_MODE_INFO *mbmi = &xd->mode_info_context->mbmi;
-  const int is_comp_pred = (mbmi->second_ref_frame > 0);
+  const int is_comp_pred = (mbmi->ref_frame[1] > 0);
   const int num_refs = is_comp_pred ? 2 : 1;
   const int this_mode = mbmi->mode;
   int i;
-  int refs[2] = { mbmi->ref_frame,
-                  (mbmi->second_ref_frame < 0 ? 0 : mbmi->second_ref_frame) };
+  int refs[2] = { mbmi->ref_frame[0],
+                  (mbmi->ref_frame[1] < 0 ? 0 : mbmi->ref_frame[1]) };
   int_mv cur_mv[2];
   int_mv ref_mv[2];
   int64_t this_rd = 0;
@@ -2091,7 +2081,7 @@
         frame_mv[refs[0]].as_int = single_newmv[refs[0]].as_int;
         frame_mv[refs[1]].as_int = single_newmv[refs[1]].as_int;
 
-        if (cpi->sf.comp_inter_joint_search)
+        if (cpi->sf.comp_inter_joint_search_thresh < bsize)
           iterative_motion_search(cpi, x, bsize, frame_mv, scaled_ref_frame,
                                   mi_row, mi_col, single_newmv);
 
@@ -2210,10 +2200,8 @@
    * are only three options: Last/Golden, ARF/Last or Golden/ARF, or in other
    * words if you present them in that order, the second one is always known
    * if the first is known */
-  *compmode_cost = vp9_cost_bit(vp9_get_pred_prob(cm, xd, PRED_COMP),
-                                is_comp_pred);
   *rate2 += vp9_cost_mv_ref(cpi, this_mode,
-                            mbmi->mb_mode_context[mbmi->ref_frame]);
+                            mbmi->mb_mode_context[mbmi->ref_frame[0]]);
 
   pred_exists = 0;
   interpolating_intpel_seen = 0;
@@ -2404,8 +2392,10 @@
   int64_t err4x4 = INT64_MAX;
   int i;
 
+  vpx_memset(&txfm_cache,0,sizeof(txfm_cache));
   ctx->skip = 0;
   xd->mode_info_context->mbmi.mode = DC_PRED;
+  xd->mode_info_context->mbmi.ref_frame[0] = INTRA_FRAME;
   err = rd_pick_intra_sby_mode(cpi, x, &rate_y, &rate_y_tokenonly,
                                &dist_y, &y_skip, bsize, txfm_cache);
   mode = xd->mode_info_context->mbmi.mode;
@@ -2458,7 +2448,7 @@
   const enum BlockSize block_size = get_plane_block_size(bsize, &xd->plane[0]);
   MB_PREDICTION_MODE this_mode;
   MB_PREDICTION_MODE best_mode = DC_PRED;
-  MV_REFERENCE_FRAME ref_frame, second_ref = INTRA_FRAME;
+  MV_REFERENCE_FRAME ref_frame;
   unsigned char segment_id = xd->mode_info_context->mbmi.segment_id;
   int comp_pred, i;
   int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES];
@@ -2478,7 +2468,8 @@
   MB_MODE_INFO best_mbmode;
   int j;
   int mode_index, best_mode_index = 0;
-  unsigned int ref_costs[MAX_REF_FRAMES];
+  unsigned int ref_costs_single[MAX_REF_FRAMES], ref_costs_comp[MAX_REF_FRAMES];
+  vp9_prob comp_mode_p;
   int64_t best_overall_rd = INT64_MAX;
   INTERPOLATIONFILTERTYPE best_filter = SWITCHABLE;
   INTERPOLATIONFILTERTYPE tmp_best_filter = SWITCHABLE;
@@ -2495,6 +2486,10 @@
   int_mv seg_mvs[4][MAX_REF_FRAMES];
   union b_mode_info best_bmodes[4];
   PARTITION_INFO best_partition;
+  int bwsl = b_width_log2(bsize);
+  int bws = (1 << bwsl) / 4;  // mode_info step for subsize
+  int bhsl = b_height_log2(bsize);
+  int bhs = (1 << bhsl) / 4;  // mode_info step for subsize
 
   for (i = 0; i < 4; i++) {
     int j;
@@ -2507,7 +2502,8 @@
   ctx->modes_with_high_error = 0;
 
   xd->mode_info_context->mbmi.segment_id = segment_id;
-  estimate_ref_frame_costs(cpi, segment_id, ref_costs);
+  estimate_ref_frame_costs(cpi, segment_id, ref_costs_single, ref_costs_comp,
+                           &comp_mode_p);
   vpx_memset(&best_mbmode, 0, sizeof(best_mbmode));
   vpx_memset(&single_newmv, 0, sizeof(single_newmv));
 
@@ -2560,6 +2556,7 @@
   if (cpi->speed == 0
       || (cpi->speed > 0 && (ref_frame_mask & (1 << INTRA_FRAME)))) {
     mbmi->mode = DC_PRED;
+    mbmi->ref_frame[0] = INTRA_FRAME;
     for (i = 0; i <= (bsize < BLOCK_SIZE_MB16X16 ? TX_4X4 :
                       (bsize < BLOCK_SIZE_SB32X32 ? TX_8X8 :
                        (bsize < BLOCK_SIZE_SB64X64 ? TX_16X16 : TX_32X32)));
@@ -2577,7 +2574,6 @@
     int mode_excluded = 0;
     int64_t this_rd = INT64_MAX;
     int disable_skip = 0;
-    int other_cost = 0;
     int compmode_cost = 0;
     int rate2 = 0, rate_y = 0, rate_uv = 0;
     int distortion2 = 0, distortion_y = 0, distortion_uv = 0;
@@ -2589,9 +2585,9 @@
       txfm_cache[i] = INT64_MAX;
 
     // Test best rd so far against threshold for trying this mode.
-    if (bsize >= BLOCK_SIZE_SB8X8 &&
-        (best_rd < cpi->rd_threshes[mode_index] ||
-         cpi->rd_threshes[mode_index] == INT_MAX))
+    if ((best_rd < ((cpi->rd_threshes[bsize][mode_index] *
+                     cpi->rd_thresh_freq_fact[bsize][mode_index]) >> 4)) ||
+        cpi->rd_threshes[bsize][mode_index] == INT_MAX)
       continue;
 
     x->skip = 0;
@@ -2612,39 +2608,39 @@
       }
     }
 
-    mbmi->ref_frame = ref_frame;
-    mbmi->second_ref_frame = vp9_mode_order[mode_index].second_ref_frame;
+    mbmi->ref_frame[0] = ref_frame;
+    mbmi->ref_frame[1] = vp9_mode_order[mode_index].second_ref_frame;
 
     if (!(ref_frame == INTRA_FRAME
         || (cpi->ref_frame_flags & flag_list[ref_frame]))) {
       continue;
     }
-    if (!(mbmi->second_ref_frame == NONE
-        || (cpi->ref_frame_flags & flag_list[mbmi->second_ref_frame]))) {
+    if (!(mbmi->ref_frame[1] == NONE
+        || (cpi->ref_frame_flags & flag_list[mbmi->ref_frame[1]]))) {
       continue;
     }
 
     // TODO(jingning, jkoleszar): scaling reference frame not supported for
     // SPLITMV.
-    if (mbmi->ref_frame > 0 &&
-          (scale_factor[mbmi->ref_frame].x_num !=
-           scale_factor[mbmi->ref_frame].x_den ||
-           scale_factor[mbmi->ref_frame].y_num !=
-           scale_factor[mbmi->ref_frame].y_den) &&
+    if (mbmi->ref_frame[0] > 0 &&
+          (scale_factor[mbmi->ref_frame[0]].x_num !=
+           scale_factor[mbmi->ref_frame[0]].x_den ||
+           scale_factor[mbmi->ref_frame[0]].y_num !=
+           scale_factor[mbmi->ref_frame[0]].y_den) &&
         this_mode == SPLITMV)
       continue;
 
-    if (mbmi->second_ref_frame > 0 &&
-          (scale_factor[mbmi->second_ref_frame].x_num !=
-           scale_factor[mbmi->second_ref_frame].x_den ||
-           scale_factor[mbmi->second_ref_frame].y_num !=
-           scale_factor[mbmi->second_ref_frame].y_den) &&
+    if (mbmi->ref_frame[1] > 0 &&
+          (scale_factor[mbmi->ref_frame[1]].x_num !=
+           scale_factor[mbmi->ref_frame[1]].x_den ||
+           scale_factor[mbmi->ref_frame[1]].y_num !=
+           scale_factor[mbmi->ref_frame[1]].y_den) &&
         this_mode == SPLITMV)
       continue;
 
-    set_scale_factors(xd, mbmi->ref_frame, mbmi->second_ref_frame,
+    set_scale_factors(xd, mbmi->ref_frame[0], mbmi->ref_frame[1],
                       scale_factor);
-    comp_pred = mbmi->second_ref_frame > INTRA_FRAME;
+    comp_pred = mbmi->ref_frame[1] > INTRA_FRAME;
     mbmi->mode = this_mode;
     mbmi->uv_mode = DC_PRED;
 
@@ -2661,24 +2657,18 @@
       continue;
 
     if (comp_pred) {
-      if (ref_frame == ALTREF_FRAME) {
-        second_ref = LAST_FRAME;
-      } else {
-        second_ref = ref_frame + 1;
-      }
-      if (!(cpi->ref_frame_flags & flag_list[second_ref]))
+      if (!(cpi->ref_frame_flags & flag_list[mbmi->ref_frame[1]]))
         continue;
-      mbmi->second_ref_frame = second_ref;
-      set_scale_factors(xd, mbmi->ref_frame, mbmi->second_ref_frame,
+      set_scale_factors(xd, mbmi->ref_frame[0], mbmi->ref_frame[1],
                         scale_factor);
 
       mode_excluded =
           mode_excluded ?
               mode_excluded : cm->comp_pred_mode == SINGLE_PREDICTION_ONLY;
     } else {
-      // mbmi->second_ref_frame = vp9_mode_order[mode_index].second_ref_frame;
+      // mbmi->ref_frame[1] = vp9_mode_order[mode_index].ref_frame[1];
       if (ref_frame != INTRA_FRAME) {
-        if (mbmi->second_ref_frame != INTRA_FRAME)
+        if (mbmi->ref_frame[1] != INTRA_FRAME)
           mode_excluded =
               mode_excluded ?
                   mode_excluded : cm->comp_pred_mode == COMP_PREDICTION_ONLY;
@@ -2689,7 +2679,7 @@
     for (i = 0; i < MAX_MB_PLANE; i++) {
       xd->plane[i].pre[0] = yv12_mb[ref_frame][i];
       if (comp_pred)
-        xd->plane[i].pre[1] = yv12_mb[second_ref][i];
+        xd->plane[i].pre[1] = yv12_mb[mbmi->ref_frame[1]][i];
     }
 
     // If the segment reference frame feature is enabled....
@@ -2715,6 +2705,15 @@
         }
       }
     }
+    // TODO(JBB): This is to make up for the fact that we don't have sad
+    // functions that work when the block size reads outside the umv.  We
+    // should fix this either by making the motion search just work on
+    // a representative block in the boundary ( first ) and then implement a
+    // function that does sads when inside the border..
+    if (((mi_row + bhs) > cm->mi_rows || (mi_col + bws) > cm->mi_cols) &&
+        this_mode == NEWMV) {
+      continue;
+    }
 
     if (this_mode == I4X4_PRED) {
       int rate;
@@ -2736,7 +2735,6 @@
         txfm_cache[i] = txfm_cache[ONLY_4X4];
     } else if (ref_frame == INTRA_FRAME) {
       TX_SIZE uv_tx;
-      vp9_build_intra_predictors_sby_s(xd, bsize);
       super_block_yrd(cpi, x, &rate_y, &distortion_y, &skippable,
                       bsize, txfm_cache);
 
@@ -2758,7 +2756,7 @@
         rate2 += intra_cost_penalty;
       distortion2 = distortion_y + distortion_uv;
     } else if (this_mode == SPLITMV) {
-      const int is_comp_pred = mbmi->second_ref_frame > 0;
+      const int is_comp_pred = mbmi->ref_frame[1] > 0;
       int rate, distortion;
       int64_t this_rd_thresh;
       int64_t tmp_rd, tmp_best_rd = INT64_MAX, tmp_best_rdu = INT64_MAX;
@@ -2766,17 +2764,18 @@
       int tmp_best_distortion = INT_MAX, tmp_best_skippable = 0;
       int switchable_filter_index;
       int_mv *second_ref = is_comp_pred ?
-          &mbmi->ref_mvs[mbmi->second_ref_frame][0] : NULL;
+          &mbmi->ref_mvs[mbmi->ref_frame[1]][0] : NULL;
       union b_mode_info tmp_best_bmodes[16];
       MB_MODE_INFO tmp_best_mbmode;
       PARTITION_INFO tmp_best_partition;
       int pred_exists = 0;
       int uv_skippable;
 
-      this_rd_thresh = (mbmi->ref_frame == LAST_FRAME) ?
-          cpi->rd_threshes[THR_NEWMV] : cpi->rd_threshes[THR_NEWA];
-      this_rd_thresh = (mbmi->ref_frame == GOLDEN_FRAME) ?
-          cpi->rd_threshes[THR_NEWG] : this_rd_thresh;
+      this_rd_thresh = (mbmi->ref_frame[0] == LAST_FRAME) ?
+          cpi->rd_threshes[bsize][THR_NEWMV] :
+          cpi->rd_threshes[bsize][THR_NEWA];
+      this_rd_thresh = (mbmi->ref_frame[0] == GOLDEN_FRAME) ?
+          cpi->rd_threshes[bsize][THR_NEWG] : this_rd_thresh;
       xd->mode_info_context->mbmi.txfm_size = TX_4X4;
 
       for (switchable_filter_index = 0;
@@ -2788,12 +2787,12 @@
         vp9_setup_interp_filters(xd, mbmi->interp_filter, &cpi->common);
 
         tmp_rd = rd_pick_best_mbsegmentation(cpi, x,
-                                             &mbmi->ref_mvs[mbmi->ref_frame][0],
-                                             second_ref, INT64_MAX,
-                                             &rate, &rate_y, &distortion,
-                                             &skippable,
-                                             (int)this_rd_thresh, seg_mvs,
-                                             mi_row, mi_col);
+                     &mbmi->ref_mvs[mbmi->ref_frame[0]][0],
+                     second_ref, INT64_MAX,
+                     &rate, &rate_y, &distortion,
+                     &skippable,
+                     (int)this_rd_thresh, seg_mvs,
+                     mi_row, mi_col);
         if (cpi->common.mcomp_filter_type == SWITCHABLE) {
           const int rs = get_switchable_rate(cm, x);
           tmp_rd += RDCOST(x->rdmult, x->rddiv, rs, 0);
@@ -2826,12 +2825,12 @@
         // Handles the special case when a filter that is not in the
         // switchable list (bilinear, 6-tap) is indicated at the frame level
         tmp_rd = rd_pick_best_mbsegmentation(cpi, x,
-                                             &mbmi->ref_mvs[mbmi->ref_frame][0],
-                                             second_ref, INT64_MAX,
-                                             &rate, &rate_y, &distortion,
-                                             &skippable,
-                                             (int)this_rd_thresh, seg_mvs,
-                                             mi_row, mi_col);
+                     &mbmi->ref_mvs[mbmi->ref_frame[0]][0],
+                     second_ref, INT64_MAX,
+                     &rate, &rate_y, &distortion,
+                     &skippable,
+                     (int)this_rd_thresh, seg_mvs,
+                     mi_row, mi_col);
       } else {
         if (cpi->common.mcomp_filter_type == SWITCHABLE) {
           int rs = get_switchable_rate(cm, x);
@@ -2876,24 +2875,24 @@
           mode_excluded = cpi->common.comp_pred_mode == COMP_PREDICTION_ONLY;
       }
 
-      compmode_cost =
-          vp9_cost_bit(vp9_get_pred_prob(cm, xd, PRED_COMP), is_comp_pred);
+      compmode_cost = vp9_cost_bit(comp_mode_p, is_comp_pred);
     } else {
       YV12_BUFFER_CONFIG *scaled_ref_frame[2] = {NULL, NULL};
-      int fb = get_ref_frame_idx(cpi, mbmi->ref_frame);
+      int fb = get_ref_frame_idx(cpi, mbmi->ref_frame[0]);
       if (cpi->scaled_ref_idx[fb] != cm->ref_frame_map[fb])
         scaled_ref_frame[0] = &cm->yv12_fb[cpi->scaled_ref_idx[fb]];
 
       if (comp_pred) {
-        fb = get_ref_frame_idx(cpi, mbmi->second_ref_frame);
+        fb = get_ref_frame_idx(cpi, mbmi->ref_frame[1]);
         if (cpi->scaled_ref_idx[fb] != cm->ref_frame_map[fb])
           scaled_ref_frame[1] = &cm->yv12_fb[cpi->scaled_ref_idx[fb]];
       }
 
+      compmode_cost = vp9_cost_bit(comp_mode_p,
+                                   mbmi->ref_frame[1] > INTRA_FRAME);
       this_rd = handle_inter_mode(cpi, x, bsize,
                                   txfm_cache,
                                   &rate2, &distortion2, &skippable,
-                                  &compmode_cost,
                                   &rate_y, &distortion_y,
                                   &rate_uv, &distortion_uv,
                                   &mode_excluded, &disable_skip,
@@ -2910,7 +2909,11 @@
 
     // Estimate the reference frame signaling cost and add it
     // to the rolling cost variable.
-    rate2 += ref_costs[xd->mode_info_context->mbmi.ref_frame];
+    if (mbmi->ref_frame[1] > INTRA_FRAME) {
+      rate2 += ref_costs_comp[mbmi->ref_frame[0]];
+    } else {
+      rate2 += ref_costs_single[mbmi->ref_frame[0]];
+    }
 
     if (!disable_skip) {
       // Test for the condition where skip block will be activated
@@ -2938,7 +2941,6 @@
           if (skip_prob) {
             prob_skip_cost = vp9_cost_bit(skip_prob, 1);
             rate2 += prob_skip_cost;
-            other_cost += prob_skip_cost;
           }
         }
       } else if (mb_skip_allowed) {
@@ -2946,7 +2948,6 @@
         int prob_skip_cost = vp9_cost_bit(vp9_get_pred_prob(cm, xd,
                                                         PRED_MBSKIP), 0);
         rate2 += prob_skip_cost;
-        other_cost += prob_skip_cost;
       }
 
       // Calculate the final RD estimate for this mode.
@@ -2955,14 +2956,14 @@
 
 #if 0
     // Keep record of best intra distortion
-    if ((xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) &&
+    if ((xd->mode_info_context->mbmi.ref_frame[0] == INTRA_FRAME) &&
         (this_rd < best_intra_rd)) {
       best_intra_rd = this_rd;
       *returnintra = distortion2;
     }
 #endif
 
-    if (!disable_skip && mbmi->ref_frame == INTRA_FRAME)
+    if (!disable_skip && mbmi->ref_frame[0] == INTRA_FRAME)
       for (i = 0; i < NB_PREDICTION_TYPES; ++i)
         best_pred_rd[i] = MIN(best_pred_rd[i], this_rd);
 
@@ -2978,9 +2979,9 @@
           || distortion2 < mode_distortions[this_mode]) {
         mode_distortions[this_mode] = distortion2;
       }
-      if (frame_distortions[mbmi->ref_frame] == -1
-          || distortion2 < frame_distortions[mbmi->ref_frame]) {
-        frame_distortions[mbmi->ref_frame] = distortion2;
+      if (frame_distortions[mbmi->ref_frame[0]] == -1
+          || distortion2 < frame_distortions[mbmi->ref_frame[0]]) {
+        frame_distortions[mbmi->ref_frame[0]] = distortion2;
       }
     }
 
@@ -2995,7 +2996,6 @@
           mbmi->mv[0].as_int = 0;
         }
 
-        other_cost += ref_costs[xd->mode_info_context->mbmi.ref_frame];
         *returnrate = rate2;
         *returndistortion = distortion2;
         best_rd = this_rd;
@@ -3032,7 +3032,7 @@
     }
 
     /* keep record of best compound/single-only prediction */
-    if (!disable_skip && mbmi->ref_frame != INTRA_FRAME) {
+    if (!disable_skip && mbmi->ref_frame[0] != INTRA_FRAME) {
       int single_rd, hybrid_rd, single_rate, hybrid_rate;
 
       if (cpi->common.comp_pred_mode == HYBRID_PREDICTION) {
@@ -3046,10 +3046,10 @@
       single_rd = RDCOST(x->rdmult, x->rddiv, single_rate, distortion2);
       hybrid_rd = RDCOST(x->rdmult, x->rddiv, hybrid_rate, distortion2);
 
-      if (mbmi->second_ref_frame <= INTRA_FRAME &&
+      if (mbmi->ref_frame[1] <= INTRA_FRAME &&
           single_rd < best_pred_rd[SINGLE_PREDICTION_ONLY]) {
         best_pred_rd[SINGLE_PREDICTION_ONLY] = single_rd;
-      } else if (mbmi->second_ref_frame > INTRA_FRAME &&
+      } else if (mbmi->ref_frame[1] > INTRA_FRAME &&
                  single_rd < best_pred_rd[COMP_PREDICTION_ONLY]) {
         best_pred_rd[COMP_PREDICTION_ONLY] = single_rd;
       }
@@ -3110,14 +3110,34 @@
 
   assert((cm->mcomp_filter_type == SWITCHABLE) ||
          (cm->mcomp_filter_type == best_mbmode.interp_filter) ||
-         (best_mbmode.ref_frame == INTRA_FRAME));
+         (best_mbmode.ref_frame[0] == INTRA_FRAME));
 
   // Accumulate filter usage stats
   // TODO(agrange): Use RD criteria to select interpolation filter mode.
   if (is_inter_mode(best_mode))
     ++cpi->best_switchable_interp_count[vp9_switchable_interp_map[best_filter]];
 
-  // TODO(rbultje) integrate with RD thresholding
+  // Updating rd_thresh_freq_fact[] here means that the differnt
+  // partition/block sizes are handled independently based on the best
+  // choice for the current partition. It may well be better to keep a scaled
+  // best rd so far value and update rd_thresh_freq_fact based on the mode/size
+  // combination that wins out.
+  if (cpi->sf.adpative_rd_thresh) {
+    for (mode_index = 0; mode_index < MAX_MODES; ++mode_index) {
+      if (mode_index == best_mode_index) {
+        cpi->rd_thresh_freq_fact[bsize][mode_index] = BASE_RD_THRESH_FREQ_FACT;
+      } else {
+        cpi->rd_thresh_freq_fact[bsize][mode_index] += MAX_RD_THRESH_FREQ_INC;
+        if (cpi->rd_thresh_freq_fact[bsize][mode_index] >
+            (cpi->sf.adpative_rd_thresh * MAX_RD_THRESH_FREQ_FACT)) {
+          cpi->rd_thresh_freq_fact[bsize][mode_index] =
+            cpi->sf.adpative_rd_thresh * MAX_RD_THRESH_FREQ_FACT;
+        }
+      }
+    }
+  }
+
+  // TODO(rbultje) integrate with RD trd_thresh_freq_facthresholding
 #if 0
   // Reduce the activation RD thresholds for the best choice mode
   if ((cpi->rd_baseline_thresh[best_mode_index] > 0) &&
@@ -3138,11 +3158,11 @@
   if (!vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME) &&
       cpi->is_src_frame_alt_ref &&
       (cpi->oxcf.arnr_max_frames == 0) &&
-      (best_mbmode.mode != ZEROMV || best_mbmode.ref_frame != ALTREF_FRAME)
+      (best_mbmode.mode != ZEROMV || best_mbmode.ref_frame[0] != ALTREF_FRAME)
       && bsize >= BLOCK_SIZE_SB8X8) {
     mbmi->mode = ZEROMV;
-    mbmi->ref_frame = ALTREF_FRAME;
-    mbmi->second_ref_frame = NONE;
+    mbmi->ref_frame[0] = ALTREF_FRAME;
+    mbmi->ref_frame[1] = NONE;
     mbmi->mv[0].as_int = 0;
     mbmi->uv_mode = DC_PRED;
     mbmi->mb_skip_coeff = 1;
@@ -3162,19 +3182,19 @@
 
   // macroblock modes
   *mbmi = best_mbmode;
-  if (best_mbmode.ref_frame == INTRA_FRAME &&
+  if (best_mbmode.ref_frame[0] == INTRA_FRAME &&
       best_mbmode.sb_type < BLOCK_SIZE_SB8X8) {
     for (i = 0; i < 4; i++)
       xd->mode_info_context->bmi[i].as_mode = best_bmodes[i].as_mode;
   }
 
-  if (best_mbmode.ref_frame != INTRA_FRAME &&
+  if (best_mbmode.ref_frame[0] != INTRA_FRAME &&
       best_mbmode.sb_type < BLOCK_SIZE_SB8X8) {
     for (i = 0; i < 4; i++)
       xd->mode_info_context->bmi[i].as_mv[0].as_int =
           best_bmodes[i].as_mv[0].as_int;
 
-    if (mbmi->second_ref_frame > 0)
+    if (mbmi->ref_frame[1] > 0)
       for (i = 0; i < 4; i++)
         xd->mode_info_context->bmi[i].as_mv[1].as_int =
             best_bmodes[i].as_mv[1].as_int;
@@ -3204,13 +3224,13 @@
   }
 
  end:
-  set_scale_factors(xd, mbmi->ref_frame, mbmi->second_ref_frame,
+  set_scale_factors(xd, mbmi->ref_frame[0], mbmi->ref_frame[1],
                     scale_factor);
   store_coding_context(x, ctx, best_mode_index,
                        &best_partition,
-                       &mbmi->ref_mvs[mbmi->ref_frame][0],
-                       &mbmi->ref_mvs[mbmi->second_ref_frame < 0 ? 0 :
-                                      mbmi->second_ref_frame][0],
+                       &mbmi->ref_mvs[mbmi->ref_frame[0]][0],
+                       &mbmi->ref_mvs[mbmi->ref_frame[1] < 0 ? 0 :
+                                      mbmi->ref_frame[1]][0],
                        best_pred_diff, best_txfm_diff);
 
   return best_rd;
diff --git a/vp9/encoder/vp9_tokenize.c b/vp9/encoder/vp9_tokenize.c
index 3d8390b..cb05219 100644
--- a/vp9/encoder/vp9_tokenize.c
+++ b/vp9/encoder/vp9_tokenize.c
@@ -99,6 +99,7 @@
   TX_SIZE tx_size;
   int dry_run;
 };
+
 static void tokenize_b(int plane, int block, BLOCK_SIZE_TYPE bsize,
                        int ss_txfrm_size, void *arg) {
   struct tokenize_b_args* const args = arg;
@@ -129,7 +130,7 @@
   const int *scan, *nb;
   vp9_coeff_count *counts;
   vp9_coeff_probs_model *coef_probs;
-  const int ref = mbmi->ref_frame != INTRA_FRAME;
+  const int ref = mbmi->ref_frame[0] != INTRA_FRAME;
   ENTROPY_CONTEXT above_ec, left_ec;
   uint8_t token_cache[1024];
   TX_TYPE tx_type = DCT_DCT;
@@ -233,8 +234,12 @@
   } while (c < eob && ++c < seg_eob);
 
   *tp = t;
-  for (pt = 0; pt < (1 << tx_size); pt++) {
-    A[pt] = L[pt] = c > 0;
+  if (xd->mb_to_right_edge < 0 || xd->mb_to_bottom_edge < 0) {
+    set_contexts_on_border(xd, bsize, plane, tx_size, c, aoff, loff, A, L);
+  } else {
+    for (pt = 0; pt < (1 << tx_size); pt++) {
+      A[pt] = L[pt] = c > 0;
+    }
   }
 }
 
diff --git a/vp9/encoder/vp9_write_bit_buffer.h b/vp9/encoder/vp9_write_bit_buffer.h
index 18cf403..98ad3f6 100644
--- a/vp9/encoder/vp9_write_bit_buffer.h
+++ b/vp9/encoder/vp9_write_bit_buffer.h
@@ -26,8 +26,12 @@
   const int off = wb->bit_offset;
   const int p = off / CHAR_BIT;
   const int q = CHAR_BIT - 1 - off % CHAR_BIT;
-  wb->bit_buffer[p] &= ~(1 << q);
-  wb->bit_buffer[p] |= bit << q;
+  if (q == CHAR_BIT -1) {
+    wb->bit_buffer[p] = bit << q;
+  } else {
+    wb->bit_buffer[p] &= ~(1 << q);
+    wb->bit_buffer[p] |= bit << q;
+  }
   wb->bit_offset = off + 1;
 }
 
diff --git a/vp9/vp9_dx_iface.c b/vp9/vp9_dx_iface.c
index b5aa10d..32cd620 100644
--- a/vp9/vp9_dx_iface.c
+++ b/vp9/vp9_dx_iface.c
@@ -217,7 +217,7 @@
   else {
     si->is_kf = 0;
 
-    if (data_sz >= 8 && !(data[0] & 0x80)) { /* I-Frame */
+    if (data_sz >= 8 && (data[0] & 0xD8) == 0x80) { /* I-Frame */
       const uint8_t *c = data + 1;
       si->is_kf = 1;