Merge "Using struct twopass_rc* instead of VP9_COMP*."
diff --git a/build/make/Makefile b/build/make/Makefile
index 030c1b5..6894d6d 100644
--- a/build/make/Makefile
+++ b/build/make/Makefile
@@ -390,7 +390,7 @@
     DIST-SRCS-$(CONFIG_MSVS)  += build/make/gen_msvs_def.sh
     DIST-SRCS-$(CONFIG_MSVS)  += build/make/gen_msvs_proj.sh
     DIST-SRCS-$(CONFIG_MSVS)  += build/make/gen_msvs_sln.sh
-    DIST-SRCS-$(CONFIG_MSVS)  += build/x86-msvs/yasm.rules
+    DIST-SRCS-$(CONFIG_MSVS)  += build/make/gen_msvs_vcxproj.sh
     DIST-SRCS-$(CONFIG_MSVS)  += build/x86-msvs/obj_int_extract.bat
     DIST-SRCS-$(CONFIG_MSVS)  += build/arm-msvs/obj_int_extract.bat
     DIST-SRCS-$(CONFIG_RVCT) += build/make/armlink_adapter.sh
diff --git a/ivfdec.c b/ivfdec.c
index 4a0816f..a37a44c 100644
--- a/ivfdec.c
+++ b/ivfdec.c
@@ -17,11 +17,6 @@
   char raw_hdr[32];
   int is_ivf = 0;
 
-  // TODO(tomfinegan): This can eventually go away, but for now it's required
-  // because the means by which file types are detected differ in vpxdec and
-  // vpxenc.
-  rewind(input_ctx->file);
-
   if (fread(raw_hdr, 1, 32, input_ctx->file) == 32) {
     if (raw_hdr[0] == 'D' && raw_hdr[1] == 'K' &&
         raw_hdr[2] == 'I' && raw_hdr[3] == 'F') {
diff --git a/vp9/common/vp9_alloccommon.c b/vp9/common/vp9_alloccommon.c
index 6d48542..ff20553 100644
--- a/vp9/common/vp9_alloccommon.c
+++ b/vp9/common/vp9_alloccommon.c
@@ -161,9 +161,6 @@
   cm->new_fb_idx = cm->fb_count - 1;
   cm->fb_idx_ref_cnt[cm->new_fb_idx] = 1;
 
-  for (i = 0; i < REFS_PER_FRAME; i++)
-    cm->active_ref_idx[i] = i;
-
   for (i = 0; i < REF_FRAMES; i++) {
     cm->ref_frame_map[i] = i;
     cm->fb_idx_ref_cnt[i] = 1;
diff --git a/vp9/common/vp9_blockd.h b/vp9/common/vp9_blockd.h
index 38acf1e..c6af7f6 100644
--- a/vp9/common/vp9_blockd.h
+++ b/vp9/common/vp9_blockd.h
@@ -212,11 +212,17 @@
 
 #define BLOCK_OFFSET(x, i) ((x) + (i) * 16)
 
+typedef struct RefBuffer {
+  // TODO(dkovalev): idx is not really required and should be removed, now it
+  // is used in vp9_onyxd_if.c
+  int idx;
+  YV12_BUFFER_CONFIG *buf;
+  struct scale_factors sf;
+} RefBuffer;
+
 typedef struct macroblockd {
   struct macroblockd_plane plane[MAX_MB_PLANE];
 
-  const struct scale_factors *scale_factors[2];
-
   MODE_INFO *last_mi;
   int mode_info_stride;
 
@@ -235,7 +241,7 @@
   int mb_to_bottom_edge;
 
   /* pointers to reference frames */
-  const YV12_BUFFER_CONFIG *ref_buf[2];
+  RefBuffer *block_refs[2];
 
   /* pointer to current frame */
   const YV12_BUFFER_CONFIG *cur_buf;
diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h
index ed4c044..b5ed959 100644
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -121,8 +121,8 @@
   // roll new_fb_idx into it.
 
   // Each frame can reference REFS_PER_FRAME buffers
-  int active_ref_idx[REFS_PER_FRAME];
-  struct scale_factors active_ref_scale[REFS_PER_FRAME];
+  RefBuffer frame_refs[REFS_PER_FRAME];
+
   int new_fb_idx;
 
   YV12_BUFFER_CONFIG post_proc_buffer;
@@ -224,13 +224,6 @@
   uint32_t fb_idx_ref_lru_count;
 } VP9_COMMON;
 
-// ref == 0 => LAST_FRAME
-// ref == 1 => GOLDEN_FRAME
-// ref == 2 => ALTREF_FRAME
-static YV12_BUFFER_CONFIG *get_frame_ref_buffer(VP9_COMMON *cm, int ref) {
-  return &cm->yv12_fb[cm->active_ref_idx[ref]];
-}
-
 static YV12_BUFFER_CONFIG *get_frame_new_buffer(VP9_COMMON *cm) {
   return &cm->yv12_fb[cm->new_fb_idx];
 }
diff --git a/vp9/common/vp9_reconinter.c b/vp9/common/vp9_reconinter.c
index c84007e..397f446 100644
--- a/vp9/common/vp9_reconinter.c
+++ b/vp9/common/vp9_reconinter.c
@@ -153,7 +153,7 @@
   int ref;
 
   for (ref = 0; ref < 1 + is_compound; ++ref) {
-    const struct scale_factors *const sf = xd->scale_factors[ref];
+    const struct scale_factors *const sf = &xd->block_refs[ref]->sf;
     struct buf_2d *const pre_buf = &pd->pre[ref];
     struct buf_2d *const dst_buf = &pd->dst;
     uint8_t *const dst = dst_buf->buf + dst_buf->stride * y + x;
@@ -256,7 +256,7 @@
   int ref;
 
   for (ref = 0; ref < 1 + is_compound; ++ref) {
-    const struct scale_factors *const sf = xd->scale_factors[ref];
+    const struct scale_factors *const sf = &xd->block_refs[ref]->sf;
     struct buf_2d *const pre_buf = &pd->pre[ref];
     struct buf_2d *const dst_buf = &pd->dst;
     uint8_t *const dst = dst_buf->buf + dst_buf->stride * y + x;
@@ -283,7 +283,7 @@
     int xs, ys, x0, y0, x0_16, y0_16, x1, y1, frame_width,
         frame_height, subpel_x, subpel_y;
     uint8_t *ref_frame, *buf_ptr;
-    const YV12_BUFFER_CONFIG *ref_buf = xd->ref_buf[ref];
+    const YV12_BUFFER_CONFIG *ref_buf = xd->block_refs[ref]->buf;
 
     // Get reference frame pointer, width and height.
     if (plane == 0) {
@@ -390,14 +390,3 @@
     }
   }
 }
-
-// TODO(dkovalev: find better place for this function)
-void vp9_setup_scale_factors(VP9_COMMON *cm, int i) {
-  const int ref = cm->active_ref_idx[i];
-  struct scale_factors *const sf = &cm->active_ref_scale[i];
-  YV12_BUFFER_CONFIG *const fb = &cm->yv12_fb[ref];
-  vp9_setup_scale_factors_for_frame(sf,
-                                    fb->y_crop_width, fb->y_crop_height,
-                                    cm->width, cm->height);
-}
-
diff --git a/vp9/common/vp9_reconinter.h b/vp9/common/vp9_reconinter.h
index a4e968c..9f37939 100644
--- a/vp9/common/vp9_reconinter.h
+++ b/vp9/common/vp9_reconinter.h
@@ -92,10 +92,8 @@
 
 static void set_scale_factors(VP9_COMMON *cm, MACROBLOCKD *xd,
                               int ref0, int ref1) {
-  xd->scale_factors[0] = &cm->active_ref_scale[ref0 >= 0 ? ref0 : 0];
-  xd->scale_factors[1] = &cm->active_ref_scale[ref1 >= 0 ? ref1 : 0];
+  xd->block_refs[0] = &cm->frame_refs[ref0 >= 0 ? ref0 : 0];
+  xd->block_refs[1] = &cm->frame_refs[ref1 >= 0 ? ref1 : 0];
 }
 
-void vp9_setup_scale_factors(VP9_COMMON *cm, int i);
-
 #endif  // VP9_COMMON_VP9_RECONINTER_H_
diff --git a/vp9/common/vp9_rtcd_defs.sh b/vp9/common/vp9_rtcd_defs.sh
index 3025ed4..26fd7fb 100644
--- a/vp9/common/vp9_rtcd_defs.sh
+++ b/vp9/common/vp9_rtcd_defs.sh
@@ -343,25 +343,25 @@
 
 # variance
 prototype unsigned int vp9_variance32x16 "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse"
-specialize vp9_variance32x16 $sse2_x86inc
+specialize vp9_variance32x16 $sse2_x86inc $avx2_x86inc
 
 prototype unsigned int vp9_variance16x32 "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse"
 specialize vp9_variance16x32 $sse2_x86inc
 
 prototype unsigned int vp9_variance64x32 "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse"
-specialize vp9_variance64x32 $sse2_x86inc
+specialize vp9_variance64x32 $sse2_x86inc $avx2_x86inc
 
 prototype unsigned int vp9_variance32x64 "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse"
 specialize vp9_variance32x64 $sse2_x86inc
 
 prototype unsigned int vp9_variance32x32 "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse"
-specialize vp9_variance32x32 $sse2_x86inc
+specialize vp9_variance32x32 $sse2_x86inc $avx2_x86inc
 
 prototype unsigned int vp9_variance64x64 "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse"
-specialize vp9_variance64x64 $sse2_x86inc
+specialize vp9_variance64x64 $sse2_x86inc $avx2_x86inc
 
 prototype unsigned int vp9_variance16x16 "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse"
-specialize vp9_variance16x16 mmx $sse2_x86inc
+specialize vp9_variance16x16 mmx $sse2_x86inc $avx2_x86inc
 
 prototype unsigned int vp9_variance16x8 "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse"
 specialize vp9_variance16x8 mmx $sse2_x86inc
@@ -662,7 +662,7 @@
 #specialize vp9_sub_pixel_mse16x16 sse2 mmx
 
 prototype unsigned int vp9_mse16x16 "const uint8_t *src_ptr, int  source_stride, const uint8_t *ref_ptr, int  recon_stride, unsigned int *sse"
-specialize vp9_mse16x16 mmx $sse2_x86inc
+specialize vp9_mse16x16 mmx $sse2_x86inc $avx2_x86inc
 
 prototype unsigned int vp9_mse8x16 "const uint8_t *src_ptr, int  source_stride, const uint8_t *ref_ptr, int  recon_stride, unsigned int *sse"
 specialize vp9_mse8x16
diff --git a/vp9/common/vp9_systemdependent.h b/vp9/common/vp9_systemdependent.h
index 254a431..7c277c3 100644
--- a/vp9/common/vp9_systemdependent.h
+++ b/vp9/common/vp9_systemdependent.h
@@ -12,6 +12,7 @@
 #define VP9_COMMON_VP9_SYSTEMDEPENDENT_H_
 
 #ifdef _MSC_VER
+#include <intrin.h>
 #include <math.h>
 #define snprintf _snprintf
 #endif
@@ -34,6 +35,16 @@
 }
 #endif
 
+static const inline int get_msb(int x) {
+#ifdef _MSC_VER
+int r = 0;
+_BitScanReverse(&r, x);
+return r;
+#else
+return 31 ^ __builtin_clz(x);
+#endif
+}
+
 struct VP9Common;
 void vp9_machine_specific_config(struct VP9Common *cm);
 
diff --git a/vp9/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c
index de6dbdc..59faccd 100644
--- a/vp9/decoder/vp9_decodeframe.c
+++ b/vp9/decoder/vp9_decodeframe.c
@@ -378,18 +378,13 @@
 static void set_ref(VP9_COMMON *const cm, MACROBLOCKD *const xd,
                     int idx, int mi_row, int mi_col) {
   MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
-  const int ref = mbmi->ref_frame[idx] - LAST_FRAME;
-  const YV12_BUFFER_CONFIG *cfg = get_frame_ref_buffer(cm, ref);
-  const struct scale_factors *sf = &cm->active_ref_scale[ref];
-
-  xd->ref_buf[idx] = cfg;
-  if (!vp9_is_valid_scale(sf))
+  RefBuffer *ref_buffer = &cm->frame_refs[mbmi->ref_frame[idx] - LAST_FRAME];
+  xd->block_refs[idx] = ref_buffer;
+  if (!vp9_is_valid_scale(&ref_buffer->sf))
     vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
                        "Invalid scale factors");
-
-  xd->scale_factors[idx] = sf;
-  setup_pre_planes(xd, idx, cfg, mi_row, mi_col, xd->scale_factors[idx]);
-  xd->corrupted |= cfg->corrupted;
+  setup_pre_planes(xd, idx, ref_buffer->buf, mi_row, mi_col, &ref_buffer->sf);
+  xd->corrupted |= ref_buffer->buf->corrupted;
 }
 
 static void decode_modes_b(VP9_COMMON *const cm, MACROBLOCKD *const xd,
@@ -737,9 +732,9 @@
   int found = 0, i;
   for (i = 0; i < REFS_PER_FRAME; ++i) {
     if (vp9_rb_read_bit(rb)) {
-      YV12_BUFFER_CONFIG *const cfg = get_frame_ref_buffer(cm, i);
-      width = cfg->y_crop_width;
-      height = cfg->y_crop_height;
+      YV12_BUFFER_CONFIG *const buf = cm->frame_refs[i].buf;
+      width = buf->y_crop_width;
+      height = buf->y_crop_height;
       found = 1;
       break;
     }
@@ -1171,8 +1166,10 @@
 
     pbi->refresh_frame_flags = (1 << REF_FRAMES) - 1;
 
-    for (i = 0; i < REFS_PER_FRAME; ++i)
-      cm->active_ref_idx[i] = cm->new_fb_idx;
+    for (i = 0; i < REFS_PER_FRAME; ++i) {
+      cm->frame_refs[i].idx = cm->new_fb_idx;
+      cm->frame_refs[i].buf = get_frame_new_buffer(cm);
+    }
 
     setup_frame_size(pbi, rb);
   } else {
@@ -1191,7 +1188,9 @@
 
       for (i = 0; i < REFS_PER_FRAME; ++i) {
         const int ref = vp9_rb_read_literal(rb, REF_FRAMES_LOG2);
-        cm->active_ref_idx[i] = cm->ref_frame_map[ref];
+        const int idx = cm->ref_frame_map[ref];
+        cm->frame_refs[i].idx = idx;
+        cm->frame_refs[i].buf = &cm->yv12_fb[idx];
         cm->ref_frame_sign_bias[LAST_FRAME + i] = vp9_rb_read_bit(rb);
       }
 
@@ -1201,9 +1200,13 @@
       cm->mcomp_filter_type = read_interp_filter_type(rb);
 
       for (i = 0; i < REFS_PER_FRAME; ++i) {
-        vp9_setup_scale_factors(cm, i);
-        if (vp9_is_scaled(&cm->active_ref_scale[i]))
-          vp9_extend_frame_borders(&cm->yv12_fb[cm->active_ref_idx[i]],
+        RefBuffer *const ref_buf = &cm->frame_refs[i];
+        vp9_setup_scale_factors_for_frame(&ref_buf->sf,
+                                          ref_buf->buf->y_crop_width,
+                                          ref_buf->buf->y_crop_height,
+                                          cm->width, cm->height);
+        if (vp9_is_scaled(&ref_buf->sf))
+          vp9_extend_frame_borders(ref_buf->buf,
                                    cm->subsampling_x, cm->subsampling_y);
       }
     }
diff --git a/vp9/decoder/vp9_onyxd_if.c b/vp9/decoder/vp9_onyxd_if.c
index d585b91..75d52c2 100644
--- a/vp9/decoder/vp9_onyxd_if.c
+++ b/vp9/decoder/vp9_onyxd_if.c
@@ -219,7 +219,7 @@
                                       YV12_BUFFER_CONFIG *sd) {
   VP9D_COMP *pbi = (VP9D_COMP *) ptr;
   VP9_COMMON *cm = &pbi->common;
-  int *ref_fb_ptr = NULL;
+  RefBuffer *ref_buf = NULL;
 
   /* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
    * encoder is using the frame buffers for. This is just a stub to keep the
@@ -227,21 +227,23 @@
    * later commit that adds VP9-specific controls for this functionality.
    */
   if (ref_frame_flag == VP9_LAST_FLAG) {
-    ref_fb_ptr = &pbi->common.active_ref_idx[0];
+    ref_buf = &cm->frame_refs[0];
   } else if (ref_frame_flag == VP9_GOLD_FLAG) {
-    ref_fb_ptr = &pbi->common.active_ref_idx[1];
+    ref_buf = &cm->frame_refs[1];
   } else if (ref_frame_flag == VP9_ALT_FLAG) {
-    ref_fb_ptr = &pbi->common.active_ref_idx[2];
+    ref_buf = &cm->frame_refs[2];
   } else {
     vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
                        "Invalid reference frame");
     return pbi->common.error.error_code;
   }
 
-  if (!equal_dimensions(&cm->yv12_fb[*ref_fb_ptr], sd)) {
+  if (!equal_dimensions(ref_buf->buf, sd)) {
     vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
                        "Incorrect buffer dimensions");
   } else {
+    int *ref_fb_ptr = &ref_buf->idx;
+
     // Find an empty frame buffer.
     const int free_fb = get_free_fb(cm);
     // Decrease fb_idx_ref_cnt since it will be increased again in
@@ -250,7 +252,8 @@
 
     // Manage the reference counters and copy image.
     ref_cnt_fb(cm->fb_idx_ref_cnt, ref_fb_ptr, free_fb);
-    vp8_yv12_copy_frame(sd, &cm->yv12_fb[*ref_fb_ptr]);
+    ref_buf->buf = &cm->yv12_fb[*ref_fb_ptr];
+    vp8_yv12_copy_frame(sd, ref_buf->buf);
   }
 
   return pbi->common.error.error_code;
@@ -285,7 +288,7 @@
 
   // Invalidate these references until the next frame starts.
   for (ref_index = 0; ref_index < 3; ref_index++)
-    cm->active_ref_idx[ref_index] = INT_MAX;
+    cm->frame_refs[ref_index].idx = INT_MAX;
 }
 
 int vp9_receive_compressed_data(VP9D_PTR ptr,
@@ -317,8 +320,8 @@
      * at this point, but if it becomes so, [0] may not always be the correct
      * thing to do here.
      */
-    if (cm->active_ref_idx[0] != INT_MAX)
-      get_frame_ref_buffer(cm, 0)->corrupted = 1;
+    if (cm->frame_refs[0].idx != INT_MAX)
+      cm->frame_refs[0].buf->corrupted = 1;
   }
 
   cm->new_fb_idx = get_free_fb(cm);
@@ -334,8 +337,8 @@
      * at this point, but if it becomes so, [0] may not always be the correct
      * thing to do here.
      */
-    if (cm->active_ref_idx[0] != INT_MAX)
-      get_frame_ref_buffer(cm, 0)->corrupted = 1;
+    if (cm->frame_refs[0].idx != INT_MAX)
+      cm->frame_refs[0].buf->corrupted = 1;
 
     if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
       cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c
index b4d4ef5..bab6a97 100644
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -1090,12 +1090,11 @@
 static void write_frame_size_with_refs(VP9_COMP *cpi,
                                        struct vp9_write_bit_buffer *wb) {
   VP9_COMMON *const cm = &cpi->common;
-  int refs[REFS_PER_FRAME] = {cpi->lst_fb_idx, cpi->gld_fb_idx,
-                              cpi->alt_fb_idx};
-  int i, found = 0;
+  int found = 0;
 
-  for (i = 0; i < REFS_PER_FRAME; ++i) {
-    YV12_BUFFER_CONFIG *cfg = &cm->yv12_fb[cm->ref_frame_map[refs[i]]];
+  MV_REFERENCE_FRAME ref_frame;
+  for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
+    YV12_BUFFER_CONFIG *cfg = get_ref_frame_buffer(cpi, ref_frame);
     found = cm->width == cfg->y_crop_width &&
             cm->height == cfg->y_crop_height;
 
@@ -1159,8 +1158,6 @@
 
     write_frame_size(cpi, wb);
   } else {
-    const int refs[REFS_PER_FRAME] = {cpi->lst_fb_idx, cpi->gld_fb_idx,
-                                      cpi->alt_fb_idx};
     if (!cm->show_frame)
       vp9_wb_write_bit(wb, cm->intra_only);
 
@@ -1173,11 +1170,12 @@
       vp9_wb_write_literal(wb, get_refresh_mask(cpi), REF_FRAMES);
       write_frame_size(cpi, wb);
     } else {
-      int i;
+      MV_REFERENCE_FRAME ref_frame;
       vp9_wb_write_literal(wb, get_refresh_mask(cpi), REF_FRAMES);
-      for (i = 0; i < REFS_PER_FRAME; ++i) {
-        vp9_wb_write_literal(wb, refs[i], REF_FRAMES_LOG2);
-        vp9_wb_write_bit(wb, cm->ref_frame_sign_bias[LAST_FRAME + i]);
+      for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
+        vp9_wb_write_literal(wb, get_ref_frame_idx(cpi, ref_frame),
+                             REF_FRAMES_LOG2);
+        vp9_wb_write_bit(wb, cm->ref_frame_sign_bias[ref_frame]);
       }
 
       write_frame_size_with_refs(cpi, wb);
diff --git a/vp9/encoder/vp9_block.h b/vp9/encoder/vp9_block.h
index 374f429..c011948 100644
--- a/vp9/encoder/vp9_block.h
+++ b/vp9/encoder/vp9_block.h
@@ -62,9 +62,6 @@
 
   // Bit flag for each mode whether it has high error in comparison to others.
   unsigned int modes_with_high_error;
-
-  // Bit flag for each ref frame whether it has high error compared to others.
-  unsigned int frames_with_high_error;
 } PICK_MODE_CONTEXT;
 
 struct macroblock_plane {
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index 800dc49..a4d5fbe 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -107,11 +107,9 @@
 static unsigned int get_sby_perpixel_variance(VP9_COMP *cpi, MACROBLOCK *x,
                                               BLOCK_SIZE bs) {
   unsigned int var, sse;
-  var = cpi->fn_ptr[bs].vf(x->plane[0].src.buf,
-                           x->plane[0].src.stride,
+  var = cpi->fn_ptr[bs].vf(x->plane[0].src.buf, x->plane[0].src.stride,
                            VP9_VAR_OFFS, 0, &sse);
-  return (var + (1 << (num_pels_log2_lookup[bs] - 1))) >>
-      num_pels_log2_lookup[bs];
+  return ROUND_POWER_OF_TWO(var, num_pels_log2_lookup[bs]);
 }
 
 // Original activity measure from Tim T's code.
@@ -1996,8 +1994,7 @@
   vp9_setup_src_planes(x, cpi->Source, 0, 0);
 
   // TODO(jkoleszar): are these initializations required?
-  setup_pre_planes(xd, 0, &cm->yv12_fb[cm->ref_frame_map[cpi->lst_fb_idx]],
-                   0, 0, NULL);
+  setup_pre_planes(xd, 0, get_ref_frame_buffer(cpi, LAST_FRAME), 0, 0, NULL);
   setup_dst_planes(xd, get_frame_new_buffer(cm), 0, 0);
 
   setup_block_dptrs(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
@@ -2586,11 +2583,10 @@
     int ref;
     const int is_compound = has_second_ref(mbmi);
     for (ref = 0; ref < 1 + is_compound; ++ref) {
-      YV12_BUFFER_CONFIG *cfg = &cm->yv12_fb[cm->ref_frame_map[
-          get_ref_frame_idx(cpi, mbmi->ref_frame[ref])]];
-      setup_pre_planes(xd, ref, cfg, mi_row, mi_col, xd->scale_factors[ref]);
+      YV12_BUFFER_CONFIG *cfg = get_ref_frame_buffer(cpi,
+                                                     mbmi->ref_frame[ref]);
+      setup_pre_planes(xd, ref, cfg, mi_row, mi_col, &xd->block_refs[ref]->sf);
     }
-
     vp9_build_inter_predictors_sb(xd, mi_row, mi_col, MAX(bsize, BLOCK_8X8));
   }
 
diff --git a/vp9/encoder/vp9_encodemb.h b/vp9/encoder/vp9_encodemb.h
index 7be6621..cb872a7 100644
--- a/vp9/encoder/vp9_encodemb.h
+++ b/vp9/encoder/vp9_encodemb.h
@@ -16,17 +16,6 @@
 #include "vp9/encoder/vp9_onyx_int.h"
 #include "vp9/common/vp9_onyxc_int.h"
 
-typedef struct {
-  MB_PREDICTION_MODE mode;
-  MV_REFERENCE_FRAME ref_frame;
-  MV_REFERENCE_FRAME second_ref_frame;
-} MODE_DEFINITION;
-
-typedef struct {
-  MV_REFERENCE_FRAME ref_frame;
-  MV_REFERENCE_FRAME second_ref_frame;
-} REF_DEFINITION;
-
 struct optimize_ctx {
   ENTROPY_CONTEXT ta[MAX_MB_PLANE][16];
   ENTROPY_CONTEXT tl[MAX_MB_PLANE][16];
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index bcee413..3e0b617 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -492,10 +492,8 @@
   int i;
 
   int recon_yoffset, recon_uvoffset;
-  const int lst_yv12_idx = cm->ref_frame_map[cpi->lst_fb_idx];
-  const int gld_yv12_idx = cm->ref_frame_map[cpi->gld_fb_idx];
-  YV12_BUFFER_CONFIG *const lst_yv12 = &cm->yv12_fb[lst_yv12_idx];
-  YV12_BUFFER_CONFIG *const gld_yv12 = &cm->yv12_fb[gld_yv12_idx];
+  YV12_BUFFER_CONFIG *const lst_yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
+  YV12_BUFFER_CONFIG *const gld_yv12 = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
   YV12_BUFFER_CONFIG *const new_yv12 = get_frame_new_buffer(cm);
   const int recon_y_stride = lst_yv12->y_stride;
   const int recon_uv_stride = lst_yv12->uv_stride;
@@ -961,31 +959,6 @@
   return fclamp(pow(error_term, power_term), 0.05, 5.0);
 }
 
-// Given a current maxQ value sets a range for future values.
-// PGW TODO..
-// This code removes direct dependency on QIndex to determine the range
-// (now uses the actual quantizer) but has not been tuned.
-static void adjust_maxq_qrange(VP9_COMP *cpi) {
-  int i;
-  // Set the max corresponding to cpi->rc.avg_q * 2.0
-  double q = cpi->rc.avg_q * 2.0;
-  cpi->twopass.maxq_max_limit = cpi->rc.worst_quality;
-  for (i = cpi->rc.best_quality; i <= cpi->rc.worst_quality; i++) {
-    cpi->twopass.maxq_max_limit = i;
-    if (vp9_convert_qindex_to_q(i) >= q)
-      break;
-  }
-
-  // Set the min corresponding to cpi->rc.avg_q * 0.5
-  q = cpi->rc.avg_q * 0.5;
-  cpi->twopass.maxq_min_limit = cpi->rc.best_quality;
-  for (i = cpi->rc.worst_quality; i >= cpi->rc.best_quality; i--) {
-    cpi->twopass.maxq_min_limit = i;
-    if (vp9_convert_qindex_to_q(i) <= q)
-      break;
-  }
-}
-
 static int estimate_max_q(VP9_COMP *cpi,
                           FIRSTPASS_STATS *fpstats,
                           int section_target_bandwitdh) {
@@ -998,16 +971,15 @@
   double err_correction_factor;
 
   if (section_target_bandwitdh <= 0)
-    return cpi->twopass.maxq_max_limit;          // Highest value allowed
+    return cpi->rc.worst_quality;          // Highest value allowed
 
   target_norm_bits_per_mb = section_target_bandwitdh < (1 << 20)
                               ? (512 * section_target_bandwitdh) / num_mbs
                               : 512 * (section_target_bandwitdh / num_mbs);
 
-
   // Try and pick a max Q that will be high enough to encode the
   // content at the given rate.
-  for (q = cpi->twopass.maxq_min_limit; q < cpi->twopass.maxq_max_limit; q++) {
+  for (q = cpi->rc.best_quality; q < cpi->rc.worst_quality; q++) {
     int bits_per_mb_at_this_q;
 
     err_correction_factor = calc_correction_factor(err_per_mb,
@@ -2015,6 +1987,11 @@
   cpi->rc.per_frame_bandwidth = target_frame_size;
 }
 
+static int test_for_kf_one_pass(VP9_COMP *cpi) {
+  // Placeholder function for auto key frame
+  return 0;
+}
+
 void vp9_get_svc_params(VP9_COMP *cpi) {
   VP9_COMMON *const cm = &cpi->common;
   if ((cm->current_video_frame == 0) ||
@@ -2034,9 +2011,10 @@
   if (!cpi->refresh_alt_ref_frame &&
       (cm->current_video_frame == 0 ||
        cm->frame_flags & FRAMEFLAGS_KEY ||
-       (cpi->oxcf.auto_key && (cpi->rc.frames_since_key %
-                               cpi->key_frame_frequency == 0)))) {
+       cpi->rc.frames_to_key == 0 ||
+       (cpi->oxcf.auto_key && test_for_kf_one_pass(cpi)))) {
     cm->frame_type = KEY_FRAME;
+    cpi->rc.frames_to_key = cpi->key_frame_frequency;
   } else {
     cm->frame_type = INTER_FRAME;
   }
@@ -2055,6 +2033,8 @@
   } else {
     cm->frame_type = INTER_FRAME;
   }
+  cpi->rc.frames_to_key = INT_MAX;
+  // Do not use periodic key frames
 }
 
 void vp9_get_second_pass_params(VP9_COMP *cpi) {
@@ -2084,10 +2064,6 @@
     int section_target_bandwidth =
         (int)(cpi->twopass.bits_left / frames_left);
 
-    // guess at maxq needed in 2nd pass
-    cpi->twopass.maxq_max_limit = cpi->rc.worst_quality;
-    cpi->twopass.maxq_min_limit = cpi->rc.best_quality;
-
     tmp_q = estimate_max_q(cpi, &cpi->twopass.total_left_stats,
                            section_target_bandwidth);
 
@@ -2183,8 +2159,6 @@
   if (cpi->target_bandwidth < 0)
     cpi->target_bandwidth = 0;
 
-  cpi->rc.frames_to_key--;
-
   // Update the total stats remaining structure
   subtract_stats(&cpi->twopass.total_left_stats, &this_frame);
 }
diff --git a/vp9/encoder/vp9_mbgraph.c b/vp9/encoder/vp9_mbgraph.c
index a9e0dfd..f3ddd39 100644
--- a/vp9/encoder/vp9_mbgraph.c
+++ b/vp9/encoder/vp9_mbgraph.c
@@ -392,8 +392,7 @@
 void vp9_update_mbgraph_stats(VP9_COMP *cpi) {
   VP9_COMMON *const cm = &cpi->common;
   int i, n_frames = vp9_lookahead_depth(cpi->lookahead);
-  YV12_BUFFER_CONFIG *golden_ref =
-      &cm->yv12_fb[cm->ref_frame_map[cpi->gld_fb_idx]];
+  YV12_BUFFER_CONFIG *golden_ref = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
 
   // we need to look ahead beyond where the ARF transitions into
   // being a GF - so exit if we don't look ahead beyond that
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index 9561047..2cdf45d 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -170,17 +170,6 @@
   }
 }
 
-static void reset_segment_features(VP9_COMMON *cm) {
-  struct segmentation *const seg = &cm->seg;
-
-  // Set up default state for MB feature flags
-  seg->enabled = 0;
-  seg->update_map = 0;
-  seg->update_data = 0;
-  vpx_memset(seg->tree_probs, 255, sizeof(seg->tree_probs));
-  vp9_clearall_segfeatures(seg);
-}
-
 static void dealloc_compressor_data(VP9_COMP *cpi) {
   // Delete sementation map
   vpx_free(cpi->segmentation_map);
@@ -592,6 +581,180 @@
     sf->thresh_mult_sub8x8[THR_COMP_GA] = INT_MAX;
 }
 
+static void set_rt_speed_feature(VP9_COMMON *cm,
+                                 SPEED_FEATURES *sf,
+                                 int speed) {
+  sf->static_segmentation = 0;
+  sf->adaptive_rd_thresh = 1;
+  sf->recode_loop = (speed < 1);
+  if (speed >= 1) {
+    sf->use_square_partition_only = !frame_is_intra_only(cm);
+    sf->less_rectangular_check = 1;
+    sf->tx_size_search_method =
+        frame_is_intra_only(cm) ? USE_FULL_RD : USE_LARGESTALL;
+
+    if (MIN(cm->width, cm->height) >= 720)
+      sf->disable_split_mask = cm->show_frame ?
+      DISABLE_ALL_SPLIT :
+                                                DISABLE_ALL_INTER_SPLIT;
+    else
+      sf->disable_split_mask = DISABLE_COMPOUND_SPLIT;
+
+    sf->use_rd_breakout = 1;
+    sf->adaptive_motion_search = 1;
+    sf->adaptive_pred_filter_type = 1;
+    sf->auto_mv_step_size = 1;
+    sf->adaptive_rd_thresh = 2;
+    sf->recode_loop = 2;
+    sf->intra_y_mode_mask[TX_32X32] = INTRA_DC_H_V;
+    sf->intra_uv_mode_mask[TX_32X32] = INTRA_DC_H_V;
+    sf->intra_uv_mode_mask[TX_16X16] = INTRA_DC_H_V;
+  }
+  if (speed >= 2) {
+    sf->use_square_partition_only = !frame_is_intra_only(cm);
+    sf->less_rectangular_check = 1;
+    sf->tx_size_search_method =
+        frame_is_intra_only(cm) ? USE_FULL_RD : USE_LARGESTALL;
+
+    if (MIN(cm->width, cm->height) >= 720)
+      sf->disable_split_mask = cm->show_frame ?
+      DISABLE_ALL_SPLIT :
+                                                DISABLE_ALL_INTER_SPLIT;
+    else
+      sf->disable_split_mask = LAST_AND_INTRA_SPLIT_ONLY;
+
+    sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH
+        | FLAG_SKIP_INTRA_BESTINTER | FLAG_SKIP_COMP_BESTINTRA
+        | FLAG_SKIP_INTRA_LOWVAR;
+
+    sf->use_rd_breakout = 1;
+    sf->adaptive_motion_search = 1;
+    sf->adaptive_pred_filter_type = 2;
+    sf->auto_mv_step_size = 1;
+
+    sf->disable_filter_search_var_thresh = 50;
+    sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
+
+    sf->auto_min_max_partition_size = 1;
+    sf->use_lastframe_partitioning = LAST_FRAME_PARTITION_LOW_MOTION;
+    sf->adjust_partitioning_from_last_frame = 1;
+    sf->last_partitioning_redo_frequency = 3;
+
+    sf->adaptive_rd_thresh = 2;
+    sf->recode_loop = 2;
+    sf->use_lp32x32fdct = 1;
+    sf->mode_skip_start = 11;
+    sf->intra_y_mode_mask[TX_32X32] = INTRA_DC_H_V;
+    sf->intra_y_mode_mask[TX_16X16] = INTRA_DC_H_V;
+    sf->intra_uv_mode_mask[TX_32X32] = INTRA_DC_H_V;
+    sf->intra_uv_mode_mask[TX_16X16] = INTRA_DC_H_V;
+  }
+  if (speed >= 3) {
+    sf->use_square_partition_only = 1;
+    sf->tx_size_search_method = USE_LARGESTALL;
+
+    if (MIN(cm->width, cm->height) >= 720)
+      sf->disable_split_mask = DISABLE_ALL_SPLIT;
+    else
+      sf->disable_split_mask = DISABLE_ALL_INTER_SPLIT;
+
+    sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH
+        | FLAG_SKIP_INTRA_BESTINTER | FLAG_SKIP_COMP_BESTINTRA
+        | FLAG_SKIP_INTRA_LOWVAR;
+
+    sf->use_rd_breakout = 1;
+    sf->adaptive_motion_search = 1;
+    sf->adaptive_pred_filter_type = 2;
+    sf->auto_mv_step_size = 1;
+
+    sf->disable_filter_search_var_thresh = 100;
+    sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
+
+    sf->auto_min_max_partition_size = 1;
+    sf->use_lastframe_partitioning = LAST_FRAME_PARTITION_ALL;
+    sf->adjust_partitioning_from_last_frame = 1;
+    sf->last_partitioning_redo_frequency = 3;
+
+    sf->use_uv_intra_rd_estimate = 1;
+    sf->skip_encode_sb = 1;
+    sf->use_lp32x32fdct = 1;
+    sf->subpel_iters_per_step = 1;
+    sf->use_fast_coef_updates = 2;
+
+    sf->adaptive_rd_thresh = 4;
+    sf->mode_skip_start = 6;
+  }
+  if (speed >= 4) {
+    sf->use_square_partition_only = 1;
+    sf->tx_size_search_method = USE_LARGESTALL;
+    sf->disable_split_mask = DISABLE_ALL_SPLIT;
+
+    sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH
+        | FLAG_SKIP_INTRA_BESTINTER | FLAG_SKIP_COMP_BESTINTRA
+        | FLAG_SKIP_COMP_REFMISMATCH | FLAG_SKIP_INTRA_LOWVAR
+        | FLAG_EARLY_TERMINATE;
+
+    sf->use_rd_breakout = 1;
+    sf->adaptive_motion_search = 1;
+    sf->adaptive_pred_filter_type = 2;
+    sf->auto_mv_step_size = 1;
+
+    sf->disable_filter_search_var_thresh = 200;
+    sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
+
+    sf->auto_min_max_partition_size = 1;
+    sf->use_lastframe_partitioning = LAST_FRAME_PARTITION_ALL;
+    sf->adjust_partitioning_from_last_frame = 1;
+    sf->last_partitioning_redo_frequency = 3;
+
+    sf->use_uv_intra_rd_estimate = 1;
+    sf->skip_encode_sb = 1;
+    sf->use_lp32x32fdct = 1;
+    sf->subpel_iters_per_step = 1;
+    sf->use_fast_coef_updates = 2;
+
+    sf->adaptive_rd_thresh = 4;
+    sf->mode_skip_start = 6;
+
+    /* sf->intra_y_mode_mask = INTRA_DC_ONLY;
+     sf->intra_uv_mode_mask = INTRA_DC_ONLY;
+     sf->search_method = BIGDIA;
+     sf->disable_split_var_thresh = 64;
+     sf->disable_filter_search_var_thresh = 64; */
+  }
+  if (speed >= 5) {
+    int i;
+    sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
+    sf->use_one_partition_size_always = 1;
+    sf->always_this_block_size = BLOCK_16X16;
+    sf->tx_size_search_method =
+        frame_is_intra_only(cm) ? USE_FULL_RD : USE_LARGESTALL;
+    sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH
+        | FLAG_SKIP_INTRA_BESTINTER | FLAG_SKIP_COMP_BESTINTRA
+        | FLAG_SKIP_COMP_REFMISMATCH | FLAG_SKIP_INTRA_LOWVAR
+        | FLAG_EARLY_TERMINATE;
+    sf->use_rd_breakout = 1;
+    sf->use_lp32x32fdct = 1;
+    sf->optimize_coefficients = 0;
+    sf->auto_mv_step_size = 1;
+    // sf->reduce_first_step_size = 1;
+    // sf->reference_masking = 1;
+
+    sf->disable_split_mask = DISABLE_ALL_SPLIT;
+    sf->search_method = HEX;
+    sf->subpel_iters_per_step = 1;
+    sf->disable_split_var_thresh = 64;
+    sf->disable_filter_search_var_thresh = 500;
+    for (i = 0; i < TX_SIZES; i++) {
+      sf->intra_y_mode_mask[i] = INTRA_DC_ONLY;
+      sf->intra_uv_mode_mask[i] = INTRA_DC_ONLY;
+    }
+    sf->use_fast_coef_updates = 2;
+    sf->adaptive_rd_thresh = 4;
+    sf->mode_skip_start = 6;
+  }
+}
+
 void vp9_set_speed_features(VP9_COMP *cpi) {
   SPEED_FEATURES *sf = &cpi->sf;
   VP9_COMMON *cm = &cpi->common;
@@ -599,9 +762,9 @@
   int speed = cpi->speed;
   int i;
 
-  // Only modes 0 and 1 supported for now in experimental code basae
-  if (mode > 1)
-    mode = 1;
+  // Convert negative speed to positive
+  if (speed < 0)
+    speed = -speed;
 
   for (i = 0; i < MAX_MODES; ++i)
     cpi->mode_chosen_counts[i] = 0;
@@ -624,7 +787,6 @@
   sf->use_lp32x32fdct = 0;
   sf->adaptive_motion_search = 0;
   sf->adaptive_pred_filter_type = 0;
-  sf->use_avoid_tested_higherror = 0;
   sf->reference_masking = 0;
   sf->use_one_partition_size_always = 0;
   sf->less_rectangular_check = 0;
@@ -663,13 +825,13 @@
       break;
 
     case 1:
+
 #if CONFIG_MULTIPLE_ARF
       // Switch segmentation off.
       sf->static_segmentation = 0;
 #else
       sf->static_segmentation = 0;
 #endif
-      sf->use_avoid_tested_higherror = 1;
       sf->adaptive_rd_thresh = 1;
       sf->recode_loop = (speed < 1);
 
@@ -844,6 +1006,9 @@
         sf->mode_skip_start = 6;
       }
       break;
+    case 2:
+      set_rt_speed_feature(cm, sf, speed);
+      break;
   }; /* switch */
 
   // Set rd thresholds based on mode and speed setting
@@ -1192,7 +1357,7 @@
   cm->refresh_frame_context = 1;
   cm->reset_frame_context = 0;
 
-  reset_segment_features(cm);
+  vp9_reset_segment_features(&cm->seg);
   set_high_precision_mv(cpi, 0);
 
   {
@@ -1202,9 +1367,6 @@
       cpi->segment_encode_breakout[i] = cpi->oxcf.encode_breakout;
   }
 
-  // At the moment the first order values may not be > MAXQ
-  cpi->oxcf.fixed_q = MIN(cpi->oxcf.fixed_q, MAXQ);
-
   // local file playback mode == really big buffer
   if (cpi->oxcf.end_usage == USAGE_LOCAL_FILE_PLAYBACK) {
     cpi->oxcf.starting_buffer_level   = 60000;
@@ -1266,13 +1428,6 @@
   }
   update_frame_size(cpi);
 
-  if (cpi->oxcf.fixed_q >= 0) {
-    cpi->rc.last_q[0] = cpi->oxcf.fixed_q;
-    cpi->rc.last_q[1] = cpi->oxcf.fixed_q;
-    cpi->rc.last_q[2] = cpi->oxcf.fixed_q;
-    cpi->rc.last_boosted_qindex = cpi->oxcf.fixed_q;
-  }
-
   cpi->speed = cpi->oxcf.cpu_used;
 
   if (cpi->oxcf.lag_in_frames == 0) {
@@ -1498,7 +1653,6 @@
   init_pick_mode_context(cpi);
 
   cm->current_video_frame   = 0;
-  cpi->rc.frames_till_gf_update_due = 0;
 
   // Set reference frame sign bias for ALTREF frame to 1 (for now)
   cm->ref_frame_sign_bias[ALTREF_FRAME] = 1;
@@ -2280,53 +2434,6 @@
   vp8_yv12_extend_frame_borders(dst_fb);
 }
 
-
-static void update_alt_ref_frame_stats(VP9_COMP *cpi) {
-  // this frame refreshes means next frames don't unless specified by user
-  cpi->rc.frames_since_golden = 0;
-
-#if CONFIG_MULTIPLE_ARF
-  if (!cpi->multi_arf_enabled)
-#endif
-    // Clear the alternate reference update pending flag.
-    cpi->rc.source_alt_ref_pending = 0;
-
-  // Set the alternate reference frame active flag
-  cpi->rc.source_alt_ref_active = 1;
-}
-
-static void update_golden_frame_stats(VP9_COMP *cpi) {
-  // Update the Golden frame usage counts.
-  if (cpi->refresh_golden_frame) {
-    // this frame refreshes means next frames don't unless specified by user
-    cpi->refresh_golden_frame = 0;
-    cpi->rc.frames_since_golden = 0;
-
-    // ******** 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 &&
-        cpi->oxcf.play_alternate && !cpi->refresh_alt_ref_frame) {
-      cpi->rc.source_alt_ref_pending = 1;
-      cpi->rc.frames_till_gf_update_due = cpi->rc.baseline_gf_interval;
-    }
-
-    if (!cpi->rc.source_alt_ref_pending)
-      cpi->rc.source_alt_ref_active = 0;
-
-    // Decrement count down till next gf
-    if (cpi->rc.frames_till_gf_update_due > 0)
-      cpi->rc.frames_till_gf_update_due--;
-
-  } else if (!cpi->refresh_alt_ref_frame) {
-    // Decrement count down till next gf
-    if (cpi->rc.frames_till_gf_update_due > 0)
-      cpi->rc.frames_till_gf_update_due--;
-
-    cpi->rc.frames_since_golden++;
-  }
-}
-
 static int find_fp_qindex() {
   int i;
 
@@ -2939,7 +3046,7 @@
   if (frame_is_intra_only(cm)) {
     vp9_setup_key_frame(cpi);
     // Reset the loop filter deltas and segmentation map.
-    reset_segment_features(cm);
+    vp9_reset_segment_features(&cm->seg);
 
     // If segmentation is enabled force a map update for key frames.
     if (seg->enabled) {
@@ -2979,8 +3086,9 @@
     if (vp9_drop_frame(cpi)) {
       // Update buffer level with zero size, update frame counters, and return.
       vp9_update_buffer_level(cpi, 0);
+      cm->last_frame_type = cm->frame_type;
+      vp9_rc_postencode_update_drop_frame(cpi);
       cm->current_video_frame++;
-      cpi->rc.frames_since_key++;
       return;
     }
   }
@@ -3049,7 +3157,7 @@
   // Special case code to reduce pulsing when key frames are forced at a
   // fixed interval. Note the reconstruction error if it is the frame before
   // the force key frame
-  if (cpi->rc.next_key_frame_forced && (cpi->rc.frames_to_key == 0)) {
+  if (cpi->rc.next_key_frame_forced && cpi->rc.frames_to_key == 1) {
     cpi->ambient_err = vp9_calc_ss_err(cpi->Source, get_frame_new_buffer(cm));
   }
 
@@ -3113,8 +3221,6 @@
    * needed in motion search besides loopfilter */
   cm->last_frame_type = cm->frame_type;
 
-  vp9_rc_postencode_update(cpi, *size);
-
 #if 0
   output_frame_level_debug_stats(cpi);
 #endif
@@ -3130,13 +3236,7 @@
 
   get_ref_frame_flags(cpi);
 
-  if (cpi->oxcf.play_alternate && cpi->refresh_alt_ref_frame
-      && (cm->frame_type != KEY_FRAME))
-    // Update the alternate reference frame stats as appropriate.
-    update_alt_ref_frame_stats(cpi);
-  else
-    // Update the Golden frame stats as appropriate.
-    update_golden_frame_stats(cpi);
+  vp9_rc_postencode_update(cpi, *size);
 
   if (cm->frame_type == KEY_FRAME) {
     // Tell the caller that the frame was coded as a key frame
@@ -3150,10 +3250,6 @@
       cpi->new_frame_coding_order_period = -1;
     }
 #endif
-
-    // As this frame is a key frame the next defaults to an inter frame.
-    vp9_clear_system_state();
-    cpi->rc.frames_since_key = 0;
   } else {
     *frame_flags = cm->frame_flags&~FRAMEFLAGS_KEY;
 
@@ -3203,7 +3299,6 @@
     // Don't increment frame counters if this was an altref buffer
     // update not a real frame
     ++cm->current_video_frame;
-    ++cpi->rc.frames_since_key;
   }
   // restore prev_mi
   cm->prev_mi = cm->prev_mip + cm->mode_info_stride + 1;
@@ -3303,6 +3398,7 @@
   VP9_COMMON *cm = &cpi->common;
   struct vpx_usec_timer  cmptimer;
   YV12_BUFFER_CONFIG    *force_src_buffer = NULL;
+  const int refs[] = { cpi->lst_fb_idx, cpi->gld_fb_idx, cpi->alt_fb_idx };
   int i;
   // FILE *fp_out = fopen("enc_frame_type.txt", "a");
 
@@ -3504,16 +3600,13 @@
   }
 #endif
 
-  /* Get the mapping of L/G/A to the reference buffer pool */
-  cm->active_ref_idx[0] = cm->ref_frame_map[cpi->lst_fb_idx];
-  cm->active_ref_idx[1] = cm->ref_frame_map[cpi->gld_fb_idx];
-  cm->active_ref_idx[2] = cm->ref_frame_map[cpi->alt_fb_idx];
-
 #if 0  // CONFIG_MULTIPLE_ARF
   if (cpi->multi_arf_enabled) {
     fprintf(fp_out, "      idx(%d, %d, %d, %d) active(%d, %d, %d)",
         cpi->lst_fb_idx, cpi->gld_fb_idx, cpi->alt_fb_idx, cm->new_fb_idx,
-        cm->active_ref_idx[0], cm->active_ref_idx[1], cm->active_ref_idx[2]);
+        cm->ref_frame_map[cpi->lst_fb_idx],
+        cm->ref_frame_map[cpi->gld_fb_idx],
+        cm->ref_frame_map[cpi->alt_fb_idx]);
     if (cpi->refresh_alt_ref_frame)
       fprintf(fp_out, "  type:ARF");
     if (cpi->rc.is_src_frame_alt_ref)
@@ -3530,12 +3623,20 @@
                            cm->subsampling_x, cm->subsampling_y,
                            VP9BORDERINPIXELS, NULL, NULL, NULL);
 
-  // Calculate scaling factors for each of the 3 available references
+
   for (i = 0; i < REFS_PER_FRAME; ++i) {
-    vp9_setup_scale_factors(cm, i);
-    if (vp9_is_scaled(&cm->active_ref_scale[i]))
-      vp9_extend_frame_borders(&cm->yv12_fb[cm->active_ref_idx[i]],
-                               cm->subsampling_x, cm->subsampling_y);
+    const int idx = cm->ref_frame_map[refs[i]];
+    YV12_BUFFER_CONFIG *const buf = &cm->yv12_fb[idx];
+
+    RefBuffer *const ref_buf = &cm->frame_refs[i];
+    ref_buf->buf = buf;
+    ref_buf->idx = idx;
+    vp9_setup_scale_factors_for_frame(&ref_buf->sf,
+                                      buf->y_crop_width, buf->y_crop_height,
+                                      cm->width, cm->height);
+
+    if (vp9_is_scaled(&ref_buf->sf))
+      vp9_extend_frame_borders(buf, cm->subsampling_x, cm->subsampling_y);
   }
 
   vp9_setup_interp_filters(&cpi->mb.e_mbd, DEFAULT_INTERP_FILTER, cm);
diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h
index d32711c..abc2dda 100644
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -252,7 +252,6 @@
   LAST_FRAME_PARTITION_METHOD use_lastframe_partitioning;
   TX_SIZE_SEARCH_METHOD tx_size_search_method;
   int use_lp32x32fdct;
-  int use_avoid_tested_higherror;
   int use_one_partition_size_always;
   int less_rectangular_check;
   int use_square_partition_only;
@@ -531,8 +530,6 @@
     double modified_error_left;
     double kf_intra_err_min;
     double gf_intra_err_min;
-    int maxq_max_limit;
-    int maxq_min_limit;
     int static_scene_max_gf_interval;
     int kf_bits;
     // Remaining error from uncoded frames in a gf group. Two pass use only
@@ -666,6 +663,12 @@
   }
 }
 
+static YV12_BUFFER_CONFIG *get_ref_frame_buffer(VP9_COMP *cpi,
+                                                MV_REFERENCE_FRAME ref_frame) {
+  VP9_COMMON *const cm = &cpi->common;
+  return &cm->yv12_fb[cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)]];
+}
+
 void vp9_encode_frame(VP9_COMP *cpi);
 
 void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, size_t *size);
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index bae87b7..31b0116 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -257,16 +257,6 @@
   cpi->rc.this_frame_target = target;
 }
 
-//  Do the best we can to define the parameters for the next GF based
-//  on what information we have available.
-//
-//  In this experimental code only two pass is supported
-//  so we just use the interval determined in the two pass code.
-static void calc_gf_params(VP9_COMP *cpi) {
-  // Set the gf interval
-  cpi->rc.frames_till_gf_update_due = cpi->rc.baseline_gf_interval;
-}
-
 // Update the buffer level: leaky bucket model.
 void vp9_update_buffer_level(VP9_COMP *const cpi, int encoded_frame_size) {
   VP9_COMMON *const cm = &cpi->common;
@@ -374,8 +364,6 @@
         / one_percent_bits);
     if (percent_low > cpi->oxcf.under_shoot_pct) {
       percent_low = cpi->oxcf.under_shoot_pct;
-    } else if (percent_low < 0) {
-      percent_low = 0;
     }
     // Lower the target bandwidth for this frame.
     this_frame_target -= (this_frame_target * percent_low) / 200;
@@ -384,8 +372,6 @@
         / one_percent_bits);
     if (percent_high > cpi->oxcf.over_shoot_pct) {
       percent_high = cpi->oxcf.over_shoot_pct;
-    } else if (percent_high < 0) {
-      percent_high = 0;
     }
     // Increase the target bandwidth for this frame.
     this_frame_target += (this_frame_target * percent_high) / 200;
@@ -851,6 +837,43 @@
   return 1;
 }
 
+static void update_alt_ref_frame_stats(VP9_COMP *cpi) {
+  // this frame refreshes means next frames don't unless specified by user
+  cpi->rc.frames_since_golden = 0;
+
+#if CONFIG_MULTIPLE_ARF
+  if (!cpi->multi_arf_enabled)
+#endif
+    // Clear the alternate reference update pending flag.
+    cpi->rc.source_alt_ref_pending = 0;
+
+  // Set the alternate reference frame active flag
+  cpi->rc.source_alt_ref_active = 1;
+}
+
+static void update_golden_frame_stats(VP9_COMP *cpi) {
+  // Update the Golden frame usage counts.
+  if (cpi->refresh_golden_frame) {
+    // this frame refreshes means next frames don't unless specified by user
+    cpi->refresh_golden_frame = 0;
+    cpi->rc.frames_since_golden = 0;
+
+    if (!cpi->rc.source_alt_ref_pending)
+      cpi->rc.source_alt_ref_active = 0;
+
+    // Decrement count down till next gf
+    if (cpi->rc.frames_till_gf_update_due > 0)
+      cpi->rc.frames_till_gf_update_due--;
+
+  } else if (!cpi->refresh_alt_ref_frame) {
+    // Decrement count down till next gf
+    if (cpi->rc.frames_till_gf_update_due > 0)
+      cpi->rc.frames_till_gf_update_due--;
+
+    cpi->rc.frames_since_golden++;
+  }
+}
+
 void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) {
   VP9_COMMON *const cm = &cpi->common;
   // Update rate control heuristics
@@ -938,4 +961,24 @@
     cpi->twopass.gf_group_bits = MAX(cpi->twopass.gf_group_bits, 0);
   }
 #endif
+
+  if (cpi->oxcf.play_alternate && cpi->refresh_alt_ref_frame
+      && (cm->frame_type != KEY_FRAME))
+    // Update the alternate reference frame stats as appropriate.
+    update_alt_ref_frame_stats(cpi);
+  else
+    // Update the Golden frame stats as appropriate.
+    update_golden_frame_stats(cpi);
+
+  if (cm->frame_type == KEY_FRAME)
+    cpi->rc.frames_since_key = 0;
+  if (cm->show_frame) {
+    cpi->rc.frames_since_key++;
+    cpi->rc.frames_to_key--;
+  }
+}
+
+void vp9_rc_postencode_update_drop_frame(VP9_COMP *cpi) {
+  cpi->rc.frames_since_key++;
+  // cpi->rc.frames_to_key--;
 }
diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h
index 8293557..086755a 100644
--- a/vp9/encoder/vp9_ratectrl.h
+++ b/vp9/encoder/vp9_ratectrl.h
@@ -52,6 +52,8 @@
 // on bytes used
 void vp9_rc_postencode_update(VP9_COMP *cpi,
                               uint64_t bytes_used);
+// for dropped frames
+void vp9_rc_postencode_update_drop_frame(VP9_COMP *cpi);
 
 // estimates bits per mb for a given qindex and correction factor
 int vp9_rc_bits_per_mb(FRAME_TYPE frame_type, int qindex,
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index 46fe163..97dc1e0 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -48,53 +48,62 @@
 
 #define MIN_EARLY_TERM_INDEX    3
 
+typedef struct {
+  MB_PREDICTION_MODE mode;
+  MV_REFERENCE_FRAME ref_frame[2];
+} MODE_DEFINITION;
+
+typedef struct {
+  MV_REFERENCE_FRAME ref_frame[2];
+} REF_DEFINITION;
+
 const MODE_DEFINITION vp9_mode_order[MAX_MODES] = {
-  {NEARESTMV, LAST_FRAME,   NONE},
-  {NEARESTMV, ALTREF_FRAME, NONE},
-  {NEARESTMV, GOLDEN_FRAME, NONE},
+  {NEARESTMV, {LAST_FRAME,   NONE}},
+  {NEARESTMV, {ALTREF_FRAME, NONE}},
+  {NEARESTMV, {GOLDEN_FRAME, NONE}},
 
-  {DC_PRED,   INTRA_FRAME,  NONE},
+  {DC_PRED,   {INTRA_FRAME,  NONE}},
 
-  {NEWMV,     LAST_FRAME,   NONE},
-  {NEWMV,     ALTREF_FRAME, NONE},
-  {NEWMV,     GOLDEN_FRAME, NONE},
+  {NEWMV,     {LAST_FRAME,   NONE}},
+  {NEWMV,     {ALTREF_FRAME, NONE}},
+  {NEWMV,     {GOLDEN_FRAME, NONE}},
 
-  {NEARMV,    LAST_FRAME,   NONE},
-  {NEARMV,    ALTREF_FRAME, NONE},
-  {NEARESTMV, LAST_FRAME,   ALTREF_FRAME},
-  {NEARESTMV, GOLDEN_FRAME, ALTREF_FRAME},
+  {NEARMV,    {LAST_FRAME,   NONE}},
+  {NEARMV,    {ALTREF_FRAME, NONE}},
+  {NEARESTMV, {LAST_FRAME,   ALTREF_FRAME}},
+  {NEARESTMV, {GOLDEN_FRAME, ALTREF_FRAME}},
 
-  {TM_PRED,   INTRA_FRAME,  NONE},
+  {TM_PRED,   {INTRA_FRAME,  NONE}},
 
-  {NEARMV,    LAST_FRAME,   ALTREF_FRAME},
-  {NEWMV,     LAST_FRAME,   ALTREF_FRAME},
-  {NEARMV,    GOLDEN_FRAME, NONE},
-  {NEARMV,    GOLDEN_FRAME, ALTREF_FRAME},
-  {NEWMV,     GOLDEN_FRAME, ALTREF_FRAME},
+  {NEARMV,    {LAST_FRAME,   ALTREF_FRAME}},
+  {NEWMV,     {LAST_FRAME,   ALTREF_FRAME}},
+  {NEARMV,    {GOLDEN_FRAME, NONE}},
+  {NEARMV,    {GOLDEN_FRAME, ALTREF_FRAME}},
+  {NEWMV,     {GOLDEN_FRAME, ALTREF_FRAME}},
 
-  {ZEROMV,    LAST_FRAME,   NONE},
-  {ZEROMV,    GOLDEN_FRAME, NONE},
-  {ZEROMV,    ALTREF_FRAME, NONE},
-  {ZEROMV,    LAST_FRAME,   ALTREF_FRAME},
-  {ZEROMV,    GOLDEN_FRAME, ALTREF_FRAME},
+  {ZEROMV,    {LAST_FRAME,   NONE}},
+  {ZEROMV,    {GOLDEN_FRAME, NONE}},
+  {ZEROMV,    {ALTREF_FRAME, NONE}},
+  {ZEROMV,    {LAST_FRAME,   ALTREF_FRAME}},
+  {ZEROMV,    {GOLDEN_FRAME, ALTREF_FRAME}},
 
-  {H_PRED,    INTRA_FRAME,  NONE},
-  {V_PRED,    INTRA_FRAME,  NONE},
-  {D135_PRED, INTRA_FRAME,  NONE},
-  {D207_PRED, INTRA_FRAME,  NONE},
-  {D153_PRED, INTRA_FRAME,  NONE},
-  {D63_PRED,  INTRA_FRAME,  NONE},
-  {D117_PRED, INTRA_FRAME,  NONE},
-  {D45_PRED,  INTRA_FRAME,  NONE},
+  {H_PRED,    {INTRA_FRAME,  NONE}},
+  {V_PRED,    {INTRA_FRAME,  NONE}},
+  {D135_PRED, {INTRA_FRAME,  NONE}},
+  {D207_PRED, {INTRA_FRAME,  NONE}},
+  {D153_PRED, {INTRA_FRAME,  NONE}},
+  {D63_PRED,  {INTRA_FRAME,  NONE}},
+  {D117_PRED, {INTRA_FRAME,  NONE}},
+  {D45_PRED,  {INTRA_FRAME,  NONE}},
 };
 
 const REF_DEFINITION vp9_ref_order[MAX_REFS] = {
-  {LAST_FRAME,   NONE},
-  {GOLDEN_FRAME, NONE},
-  {ALTREF_FRAME, NONE},
-  {LAST_FRAME,   ALTREF_FRAME},
-  {GOLDEN_FRAME, ALTREF_FRAME},
-  {INTRA_FRAME,  NONE},
+  {{LAST_FRAME,   NONE}},
+  {{GOLDEN_FRAME, NONE}},
+  {{ALTREF_FRAME, NONE}},
+  {{LAST_FRAME,   ALTREF_FRAME}},
+  {{GOLDEN_FRAME, ALTREF_FRAME}},
+  {{INTRA_FRAME,  NONE}},
 };
 
 // The baseline rd thresholds for breaking out of the rd loop for
@@ -308,26 +317,14 @@
   }
 }
 
-static INLINE void linear_interpolate2(double x, int ntab, int inv_step,
-                                       const double *tab1, const double *tab2,
-                                       double *v1, double *v2) {
-  double y = x * inv_step;
-  int d = (int) y;
-  if (d >= ntab - 1) {
-    *v1 = tab1[ntab - 1];
-    *v2 = tab2[ntab - 1];
-  } else {
-    double a = y - d;
-    *v1 = tab1[d] * (1 - a) + tab1[d + 1] * a;
-    *v2 = tab2[d] * (1 - a) + tab2[d + 1] * a;
-  }
-}
+static const int MAX_XSQ_Q10 = 245727;
 
-static void model_rd_norm(double x, double *R, double *D) {
-  static const int inv_tab_step = 8;
-  static const int tab_size = 120;
+static void model_rd_norm(int xsq_q10, int *r_q10, int *d_q10) {
   // NOTE: The tables below must be of the same size
-  //
+
+  // The functions described below are sampled at the four most significant
+  // bits of x^2 + 8 / 256
+
   // Normalized rate
   // This table models the rate for a Laplacian source
   // source with given variance when quantized with a uniform quantizer
@@ -335,22 +332,20 @@
   // Rn(x) = H(sqrt(r)) + sqrt(r)*[1 + H(r)/(1 - r)],
   // where r = exp(-sqrt(2) * x) and x = qpstep / sqrt(variance),
   // and H(x) is the binary entropy function.
-  static const double rate_tab[] = {
-    64.00, 4.944, 3.949, 3.372, 2.966, 2.655, 2.403, 2.194,
-    2.014, 1.858, 1.720, 1.596, 1.485, 1.384, 1.291, 1.206,
-    1.127, 1.054, 0.986, 0.923, 0.863, 0.808, 0.756, 0.708,
-    0.662, 0.619, 0.579, 0.541, 0.506, 0.473, 0.442, 0.412,
-    0.385, 0.359, 0.335, 0.313, 0.291, 0.272, 0.253, 0.236,
-    0.220, 0.204, 0.190, 0.177, 0.165, 0.153, 0.142, 0.132,
-    0.123, 0.114, 0.106, 0.099, 0.091, 0.085, 0.079, 0.073,
-    0.068, 0.063, 0.058, 0.054, 0.050, 0.047, 0.043, 0.040,
-    0.037, 0.034, 0.032, 0.029, 0.027, 0.025, 0.023, 0.022,
-    0.020, 0.019, 0.017, 0.016, 0.015, 0.014, 0.013, 0.012,
-    0.011, 0.010, 0.009, 0.008, 0.008, 0.007, 0.007, 0.006,
-    0.006, 0.005, 0.005, 0.005, 0.004, 0.004, 0.004, 0.003,
-    0.003, 0.003, 0.003, 0.002, 0.002, 0.002, 0.002, 0.002,
-    0.002, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001,
-    0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.000,
+  static const int rate_tab_q10[] = {
+    65536,  6086,  5574,  5275,  5063,  4899,  4764,  4651,
+     4553,  4389,  4255,  4142,  4044,  3958,  3881,  3811,
+     3748,  3635,  3538,  3453,  3376,  3307,  3244,  3186,
+     3133,  3037,  2952,  2877,  2809,  2747,  2690,  2638,
+     2589,  2501,  2423,  2353,  2290,  2232,  2179,  2130,
+     2084,  2001,  1928,  1862,  1802,  1748,  1698,  1651,
+     1608,  1530,  1460,  1398,  1342,  1290,  1243,  1199,
+     1159,  1086,  1021,   963,   911,   864,   821,   781,
+      745,   680,   623,   574,   530,   490,   455,   424,
+      395,   345,   304,   269,   239,   213,   190,   171,
+      154,   126,   104,    87,    73,    61,    52,    44,
+       38,    28,    21,    16,    12,    10,     8,     6,
+        5,     3,     2,     1,     1,     1,     0,     0,
   };
   // Normalized distortion
   // This table models the normalized distortion for a Laplacian source
@@ -359,54 +354,73 @@
   // Dn(x) = 1 - 1/sqrt(2) * x / sinh(x/sqrt(2))
   // where x = qpstep / sqrt(variance)
   // Note the actual distortion is Dn * variance.
-  static const double dist_tab[] = {
-    0.000, 0.001, 0.005, 0.012, 0.021, 0.032, 0.045, 0.061,
-    0.079, 0.098, 0.119, 0.142, 0.166, 0.190, 0.216, 0.242,
-    0.269, 0.296, 0.324, 0.351, 0.378, 0.405, 0.432, 0.458,
-    0.484, 0.509, 0.534, 0.557, 0.580, 0.603, 0.624, 0.645,
-    0.664, 0.683, 0.702, 0.719, 0.735, 0.751, 0.766, 0.780,
-    0.794, 0.807, 0.819, 0.830, 0.841, 0.851, 0.861, 0.870,
-    0.878, 0.886, 0.894, 0.901, 0.907, 0.913, 0.919, 0.925,
-    0.930, 0.935, 0.939, 0.943, 0.947, 0.951, 0.954, 0.957,
-    0.960, 0.963, 0.966, 0.968, 0.971, 0.973, 0.975, 0.976,
-    0.978, 0.980, 0.981, 0.982, 0.984, 0.985, 0.986, 0.987,
-    0.988, 0.989, 0.990, 0.990, 0.991, 0.992, 0.992, 0.993,
-    0.993, 0.994, 0.994, 0.995, 0.995, 0.996, 0.996, 0.996,
-    0.996, 0.997, 0.997, 0.997, 0.997, 0.998, 0.998, 0.998,
-    0.998, 0.998, 0.998, 0.999, 0.999, 0.999, 0.999, 0.999,
-    0.999, 0.999, 0.999, 0.999, 0.999, 0.999, 0.999, 1.000,
+  static const int dist_tab_q10[] = {
+       0,     0,     1,     1,     1,     2,     2,     2,
+       3,     3,     4,     5,     5,     6,     7,     7,
+       8,     9,    11,    12,    13,    15,    16,    17,
+      18,    21,    24,    26,    29,    31,    34,    36,
+      39,    44,    49,    54,    59,    64,    69,    73,
+      78,    88,    97,   106,   115,   124,   133,   142,
+     151,   167,   184,   200,   215,   231,   245,   260,
+     274,   301,   327,   351,   375,   397,   418,   439,
+     458,   495,   528,   559,   587,   613,   637,   659,
+     680,   717,   749,   777,   801,   823,   842,   859,
+     874,   899,   919,   936,   949,   960,   969,   977,
+     983,   994,  1001,  1006,  1010,  1013,  1015,  1017,
+    1018,  1020,  1022,  1022,  1023,  1023,  1023,  1024,
+  };
+  static const int xsq_iq_q10[] = {
+         0,      4,      8,     12,     16,     20,     24,     28,
+        32,     40,     48,     56,     64,     72,     80,     88,
+        96,    112,    128,    144,    160,    176,    192,    208,
+       224,    256,    288,    320,    352,    384,    416,    448,
+       480,    544,    608,    672,    736,    800,    864,    928,
+       992,   1120,   1248,   1376,   1504,   1632,   1760,   1888,
+      2016,   2272,   2528,   2784,   3040,   3296,   3552,   3808,
+      4064,   4576,   5088,   5600,   6112,   6624,   7136,   7648,
+      8160,   9184,  10208,  11232,  12256,  13280,  14304,  15328,
+     16352,  18400,  20448,  22496,  24544,  26592,  28640,  30688,
+     32736,  36832,  40928,  45024,  49120,  53216,  57312,  61408,
+     65504,  73696,  81888,  90080,  98272, 106464, 114656, 122848,
+    131040, 147424, 163808, 180192, 196576, 212960, 229344, 245728,
   };
   /*
-  assert(sizeof(rate_tab) == tab_size * sizeof(rate_tab[0]);
-  assert(sizeof(dist_tab) == tab_size * sizeof(dist_tab[0]);
-  assert(sizeof(rate_tab) == sizeof(dist_tab));
+  static const int tab_size = sizeof(rate_tab_q10) / sizeof(rate_tab_q10[0]);
+  assert(sizeof(dist_tab_q10) / sizeof(dist_tab_q10[0]) == tab_size);
+  assert(sizeof(xsq_iq_q10) / sizeof(xsq_iq_q10[0]) == tab_size);
+  assert(MAX_XSQ_Q10 + 1 == xsq_iq_q10[tab_size - 1]);
   */
-  assert(x >= 0.0);
-  linear_interpolate2(x, tab_size, inv_tab_step,
-                      rate_tab, dist_tab, R, D);
+  int tmp = (xsq_q10 >> 2) + 8;
+  int k = get_msb(tmp) - 3;
+  int xq = (k << 3) + ((tmp >> k) & 0x7);
+  const int one_q10 = 1 << 10;
+  const int a_q10 = ((xsq_q10 - xsq_iq_q10[xq]) << 10) >> (2 + k);
+  const int b_q10 = one_q10 - a_q10;
+  *r_q10 = (rate_tab_q10[xq] * b_q10 + rate_tab_q10[xq + 1] * a_q10) >> 10;
+  *d_q10 = (dist_tab_q10[xq] * b_q10 + dist_tab_q10[xq + 1] * a_q10) >> 10;
 }
 
-static void model_rd_from_var_lapndz(int var, int n, int qstep,
-                                     int *rate, int64_t *dist) {
+static void model_rd_from_var_lapndz(unsigned int var, unsigned int n,
+                                     unsigned int qstep, int *rate,
+                                     int64_t *dist) {
   // This function models the rate and distortion for a Laplacian
   // source with given variance when quantized with a uniform quantizer
   // with given stepsize. The closed form expressions are in:
   // Hang and Chen, "Source Model for transform video coder and its
   // application - Part I: Fundamental Theory", IEEE Trans. Circ.
   // Sys. for Video Tech., April 1997.
-  vp9_clear_system_state();
-  if (var == 0 || n == 0) {
+  if (var == 0) {
     *rate = 0;
     *dist = 0;
   } else {
-    double D, R;
-    double s2 = (double) var / n;
-    double x = qstep / sqrt(s2);
-    model_rd_norm(x, &R, &D);
-    *rate = (int)((n << 8) * R + 0.5);
-    *dist = (int)(var * D + 0.5);
+    int d_q10, r_q10;
+    uint64_t xsq_q10_64 =
+        ((((uint64_t)qstep * qstep * n) << 10) + (var >> 1)) / var;
+    int xsq_q10 = xsq_q10_64 > MAX_XSQ_Q10 ? MAX_XSQ_Q10 : xsq_q10_64;
+    model_rd_norm(xsq_q10, &r_q10, &d_q10);
+    *rate = (n * r_q10 + 2) >> 2;
+    *dist = (var * (int64_t)d_q10 + 512) >> 10;
   }
-  vp9_clear_system_state();
 }
 
 static void model_rd_for_sb(VP9_COMP *cpi, BLOCK_SIZE bsize,
@@ -1524,7 +1538,7 @@
     vp9_build_inter_predictor(pre, pd->pre[ref].stride,
                               dst, pd->dst.stride,
                               &mi->bmi[i].as_mv[ref].as_mv,
-                              xd->scale_factors[ref],
+                              &xd->block_refs[ref]->sf,
                               width, height, ref, &xd->subpix, MV_PRECISION_Q3,
                               mi_col * MI_SIZE + 4 * (i % 2),
                               mi_row * MI_SIZE + 4 * (i / 2));
@@ -1632,6 +1646,7 @@
   int i, br = 0, idx, idy;
   int64_t bd = 0, block_sse = 0;
   MB_PREDICTION_MODE this_mode;
+  VP9_COMMON *cm = &cpi->common;
   MODE_INFO *mi = x->e_mbd.mi_8x8[0];
   MB_MODE_INFO *const mbmi = &mi->mbmi;
   struct macroblock_plane *const p = &x->plane[0];
@@ -1673,13 +1688,13 @@
       i = idy * 2 + idx;
 
       frame_mv[ZEROMV][mbmi->ref_frame[0]].as_int = 0;
-      vp9_append_sub8x8_mvs_for_idx(&cpi->common, &x->e_mbd, tile,
+      vp9_append_sub8x8_mvs_for_idx(cm, &x->e_mbd, tile,
                                     i, 0, mi_row, mi_col,
                                     &frame_mv[NEARESTMV][mbmi->ref_frame[0]],
                                     &frame_mv[NEARMV][mbmi->ref_frame[0]]);
       if (has_second_rf) {
         frame_mv[ZEROMV][mbmi->ref_frame[1]].as_int = 0;
-        vp9_append_sub8x8_mvs_for_idx(&cpi->common, &x->e_mbd, tile,
+        vp9_append_sub8x8_mvs_for_idx(cm, &x->e_mbd, tile,
                                       i, 1, mi_row, mi_col,
                                       &frame_mv[NEARESTMV][mbmi->ref_frame[1]],
                                       &frame_mv[NEARMV][mbmi->ref_frame[1]]);
@@ -1738,6 +1753,7 @@
         // motion search for newmv (single predictor case only)
         if (!has_second_rf && this_mode == NEWMV &&
             seg_mvs[i][mbmi->ref_frame[0]].as_int == INVALID_MV) {
+          int_mv *const new_mv = &mode_mv[NEWMV];
           int step_param = 0;
           int further_steps;
           int thissme, bestsme = INT_MAX;
@@ -1763,7 +1779,7 @@
           else
             max_mv = MAX(abs(bsi->mvp.as_mv.row), abs(bsi->mvp.as_mv.col)) >> 3;
 
-          if (cpi->sf.auto_mv_step_size && cpi->common.show_frame) {
+          if (cpi->sf.auto_mv_step_size && cm->show_frame) {
             // Take wtd average of the step_params based on the last frame's
             // max mv magnitude and the best ref mvs of the current block for
             // the given reference.
@@ -1776,7 +1792,7 @@
           mvp_full.row = bsi->mvp.as_mv.row >> 3;
           mvp_full.col = bsi->mvp.as_mv.col >> 3;
 
-          if (cpi->sf.adaptive_motion_search && cpi->common.show_frame) {
+          if (cpi->sf.adaptive_motion_search && cm->show_frame) {
             mvp_full.row = x->pred_mv[mbmi->ref_frame[0]].as_mv.row >> 3;
             mvp_full.col = x->pred_mv[mbmi->ref_frame[0]].as_mv.col >> 3;
             step_param = MAX(step_param, 8);
@@ -1793,24 +1809,24 @@
                                      step_param,
                                      sadpb, 1, v_fn_ptr, 1,
                                      &bsi->ref_mv->as_mv,
-                                     &mode_mv[NEWMV].as_mv);
+                                     &new_mv->as_mv);
           } else if (cpi->sf.search_method == SQUARE) {
             bestsme = vp9_square_search(x, &mvp_full,
                                         step_param,
                                         sadpb, 1, v_fn_ptr, 1,
                                         &bsi->ref_mv->as_mv,
-                                        &mode_mv[NEWMV].as_mv);
+                                        &new_mv->as_mv);
           } else if (cpi->sf.search_method == BIGDIA) {
             bestsme = vp9_bigdia_search(x, &mvp_full,
                                         step_param,
                                         sadpb, 1, v_fn_ptr, 1,
                                         &bsi->ref_mv->as_mv,
-                                        &mode_mv[NEWMV].as_mv);
+                                        &new_mv->as_mv);
           } else {
             bestsme = vp9_full_pixel_diamond(cpi, x, &mvp_full, step_param,
                                              sadpb, further_steps, 0, v_fn_ptr,
                                              &bsi->ref_mv->as_mv,
-                                             &mode_mv[NEWMV]);
+                                             new_mv);
           }
 
           // Should we do a full search (best quality only)
@@ -1826,20 +1842,20 @@
 
             if (thissme < bestsme) {
               bestsme = thissme;
-              mode_mv[NEWMV].as_int = mi->bmi[i].as_mv[0].as_int;
+              new_mv->as_int = mi->bmi[i].as_mv[0].as_int;
             } else {
               /* The full search result is actually worse so re-instate the
                * previous best vector */
-              mi->bmi[i].as_mv[0].as_int = mode_mv[NEWMV].as_int;
+              mi->bmi[i].as_mv[0].as_int = new_mv->as_int;
             }
           }
 
           if (bestsme < INT_MAX) {
             int distortion;
             cpi->find_fractional_mv_step(x,
-                                         &mode_mv[NEWMV].as_mv,
+                                         &new_mv->as_mv,
                                          &bsi->ref_mv->as_mv,
-                                         cpi->common.allow_high_precision_mv,
+                                         cm->allow_high_precision_mv,
                                          x->errorperbit, v_fn_ptr,
                                          0, cpi->sf.subpel_iters_per_step,
                                          x->nmvjointcost, x->mvcost,
@@ -1847,11 +1863,11 @@
                                          &x->pred_sse[mbmi->ref_frame[0]]);
 
             // save motion search result for use in compound prediction
-            seg_mvs[i][mbmi->ref_frame[0]].as_int = mode_mv[NEWMV].as_int;
+            seg_mvs[i][mbmi->ref_frame[0]].as_int = new_mv->as_int;
           }
 
           if (cpi->sf.adaptive_motion_search)
-            x->pred_mv[mbmi->ref_frame[0]].as_int = mode_mv[NEWMV].as_int;
+            x->pred_mv[mbmi->ref_frame[0]].as_int = new_mv->as_int;
 
           // restore src pointers
           mi_buf_restore(x, orig_src, orig_pre);
@@ -2108,16 +2124,20 @@
                      cpi->common.show_frame &&
                      block_size < cpi->sf.max_partition_size);
 
+  int_mv pred_mv[3] = {
+      mbmi->ref_mvs[ref_frame][0], mbmi->ref_mvs[ref_frame][1],
+      x->pred_mv[ref_frame]
+  };
+
   // Get the sad for each candidate reference mv
   for (i = 0; i < num_mv_refs; i++) {
-    this_mv.as_int = (i < MAX_MV_REF_CANDIDATES) ?
-        mbmi->ref_mvs[ref_frame][i].as_int : x->pred_mv[ref_frame].as_int;
+    this_mv.as_int = pred_mv[i].as_int;
 
     max_mv = MAX(max_mv,
                  MAX(abs(this_mv.as_mv.row), abs(this_mv.as_mv.col)) >> 3);
-    // The list is at an end if we see 0 for a second time.
+    // only need to check zero mv once
     if (!this_mv.as_int && zero_seen)
-      break;
+      continue;
     zero_seen = zero_seen || !this_mv.as_int;
 
     row_offset = this_mv.as_mv.row >> 3;
@@ -2268,8 +2288,7 @@
   YV12_BUFFER_CONFIG *yv12 = &cm->yv12_fb[cpi->common.ref_frame_map[idx]];
   MACROBLOCKD *const xd = &x->e_mbd;
   MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
-  const struct scale_factors *const sf =
-      &cpi->common.active_ref_scale[frame_type - 1];
+  const struct scale_factors *const sf = &cm->frame_refs[frame_type - 1].sf;
 
 
   // TODO(jkoleszar): Is the UV buffer ever used here? If so, need to make this
@@ -2325,7 +2344,7 @@
   int bestsme = INT_MAX;
   int further_steps, step_param;
   int sadpb = x->sadperbit16;
-  int_mv mvp_full;
+  MV mvp_full;
   int ref = mbmi->ref_frame[0];
   int_mv ref_mv = mbmi->ref_mvs[ref][0];
 
@@ -2336,6 +2355,10 @@
 
   YV12_BUFFER_CONFIG *scaled_ref_frame = get_scaled_ref_frame(cpi, ref);
 
+  int_mv pred_mv[3] = {
+      mbmi->ref_mvs[ref][0], mbmi->ref_mvs[ref][1], x->pred_mv[ref]
+  };
+
   if (scaled_ref_frame) {
     int i;
     // Swap out the reference frame for a version that's been scaled to
@@ -2351,21 +2374,10 @@
 
   // Adjust search parameters based on small partitions' result.
   if (x->fast_ms) {
-    // && abs(mvp_full.as_mv.row - x->pred_mv.as_mv.row) < 24 &&
-    // abs(mvp_full.as_mv.col - x->pred_mv.as_mv.col) < 24) {
     // adjust search range
     step_param = 6;
     if (x->fast_ms > 1)
       step_param = 8;
-
-    // Get prediction MV.
-    mvp_full.as_int = x->pred_mv[ref].as_int;
-
-    // Adjust MV sign if needed.
-    if (cm->ref_frame_sign_bias[ref]) {
-      mvp_full.as_mv.col *= -1;
-      mvp_full.as_mv.row *= -1;
-    }
   } else {
     // Work out the size of the first step in the mv step search.
     // 0 here is maximum length first step. 1 is MAX >> 1 etc.
@@ -2411,36 +2423,28 @@
     }
   }
 
-  mvp_full.as_int = x->mv_best_ref_index[ref] < MAX_MV_REF_CANDIDATES ?
-      mbmi->ref_mvs[ref][x->mv_best_ref_index[ref]].as_int :
-      x->pred_mv[ref].as_int;
+  mvp_full = pred_mv[x->mv_best_ref_index[ref]].as_mv;
 
-  mvp_full.as_mv.col >>= 3;
-  mvp_full.as_mv.row >>= 3;
+  mvp_full.col >>= 3;
+  mvp_full.row >>= 3;
 
   // Further step/diamond searches as necessary
   further_steps = (cpi->sf.max_step_search_steps - 1) - step_param;
 
   if (cpi->sf.search_method == HEX) {
-    bestsme = vp9_hex_search(x, &mvp_full.as_mv,
-                             step_param,
-                             sadpb, 1,
+    bestsme = vp9_hex_search(x, &mvp_full, step_param, sadpb, 1,
                              &cpi->fn_ptr[bsize], 1,
                              &ref_mv.as_mv, &tmp_mv->as_mv);
   } else if (cpi->sf.search_method == SQUARE) {
-    bestsme = vp9_square_search(x, &mvp_full.as_mv,
-                                step_param,
-                                sadpb, 1,
+    bestsme = vp9_square_search(x, &mvp_full, step_param, sadpb, 1,
                                 &cpi->fn_ptr[bsize], 1,
                                 &ref_mv.as_mv, &tmp_mv->as_mv);
   } else if (cpi->sf.search_method == BIGDIA) {
-    bestsme = vp9_bigdia_search(x, &mvp_full.as_mv,
-                                step_param,
-                                sadpb, 1,
+    bestsme = vp9_bigdia_search(x, &mvp_full, step_param, sadpb, 1,
                                 &cpi->fn_ptr[bsize], 1,
                                 &ref_mv.as_mv, &tmp_mv->as_mv);
   } else {
-    bestsme = vp9_full_pixel_diamond(cpi, x, &mvp_full.as_mv, step_param,
+    bestsme = vp9_full_pixel_diamond(cpi, x, &mvp_full, step_param,
                                      sadpb, further_steps, 1,
                                      &cpi->fn_ptr[bsize],
                                      &ref_mv.as_mv, tmp_mv);
@@ -2540,7 +2544,7 @@
                               ref_yv12[!id].stride,
                               second_pred, pw,
                               &frame_mv[refs[!id]].as_mv,
-                              xd->scale_factors[!id],
+                              &xd->block_refs[!id]->sf,
                               pw, ph, 0,
                               &xd->subpix, MV_PRECISION_Q3,
                               mi_col * MI_SIZE, mi_row * MI_SIZE);
@@ -2760,9 +2764,8 @@
                         mbmi->mode_context[mbmi->ref_frame[0]]);
 
   if (!(*mode_excluded))
-    *mode_excluded = is_comp_pred
-        ? cpi->common.reference_mode == SINGLE_REFERENCE
-        : cpi->common.reference_mode == COMPOUND_REFERENCE;
+    *mode_excluded = is_comp_pred ? cm->reference_mode == SINGLE_REFERENCE
+                                  : cm->reference_mode == COMPOUND_REFERENCE;
 
   pred_exists = 0;
   // Are all MVs integer pel for Y and UV
@@ -2894,7 +2897,7 @@
     }
   }
 
-  if (cpi->common.mcomp_filter_type == SWITCHABLE)
+  if (cm->mcomp_filter_type == SWITCHABLE)
     *rate2 += get_switchable_rate(x);
 
   if (!is_comp_pred && cpi->enable_encode_breakout) {
@@ -3124,10 +3127,6 @@
   int_mv single_newmv[MAX_REF_FRAMES] = { { 0 } };
   static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG,
                                     VP9_ALT_FLAG };
-  int idx_list[4] = {0,
-                     cpi->lst_fb_idx,
-                     cpi->gld_fb_idx,
-                     cpi->alt_fb_idx};
   int64_t best_rd = best_rd_so_far;
   int64_t best_tx_rd[TX_MODES];
   int64_t best_tx_diff[TX_MODES];
@@ -3136,7 +3135,6 @@
   int64_t best_filter_rd[SWITCHABLE_FILTER_CONTEXTS];
   int64_t best_filter_diff[SWITCHABLE_FILTER_CONTEXTS];
   MB_MODE_INFO best_mbmode = { 0 };
-  int j;
   int mode_index, best_mode_index = 0;
   unsigned int ref_costs_single[MAX_REF_FRAMES], ref_costs_comp[MAX_REF_FRAMES];
   vp9_prob comp_mode_p;
@@ -3149,10 +3147,7 @@
   int64_t dist_uv[TX_SIZES];
   int skip_uv[TX_SIZES];
   MB_PREDICTION_MODE mode_uv[TX_SIZES];
-  unsigned int ref_frame_mask = 0;
-  unsigned int mode_mask = 0;
   int64_t mode_distortions[MB_MODE_COUNT] = {-1};
-  int64_t frame_distortions[MAX_REF_FRAMES] = {-1};
   int intra_cost_penalty = 20 * vp9_dc_quant(cm->base_qindex, cm->y_dc_delta_q);
   const int bws = num_8x8_blocks_wide_lookup[bsize] / 2;
   const int bhs = num_8x8_blocks_high_lookup[bsize] / 2;
@@ -3161,7 +3156,6 @@
   x->skip_encode = cpi->sf.skip_encode_frame && x->q_index < QIDX_SKIP_THRESH;
 
   // Everywhere the flag is set the error is much higher than its neighbors.
-  ctx->frames_with_high_error = 0;
   ctx->modes_with_high_error = 0;
 
   estimate_ref_frame_costs(cpi, segment_id, ref_costs_single, ref_costs_comp,
@@ -3180,44 +3174,11 @@
 
   *returnrate = INT_MAX;
 
-  // Create a mask set to 1 for each reference frame used by a smaller
-  // resolution.
-  if (cpi->sf.use_avoid_tested_higherror) {
-    switch (block_size) {
-      case BLOCK_64X64:
-        for (i = 0; i < 4; i++) {
-          for (j = 0; j < 4; j++) {
-            ref_frame_mask |= x->mb_context[i][j].frames_with_high_error;
-            mode_mask |= x->mb_context[i][j].modes_with_high_error;
-          }
-        }
-        for (i = 0; i < 4; i++) {
-          ref_frame_mask |= x->sb32_context[i].frames_with_high_error;
-          mode_mask |= x->sb32_context[i].modes_with_high_error;
-        }
-        break;
-      case BLOCK_32X32:
-        for (i = 0; i < 4; i++) {
-          ref_frame_mask |=
-              x->mb_context[x->sb_index][i].frames_with_high_error;
-          mode_mask |= x->mb_context[x->sb_index][i].modes_with_high_error;
-        }
-        break;
-      default:
-        // Until we handle all block sizes set it to present;
-        ref_frame_mask = 0;
-        mode_mask = 0;
-        break;
-    }
-    ref_frame_mask = ~ref_frame_mask;
-    mode_mask = ~mode_mask;
-  }
-
   for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) {
     x->pred_mv_sad[ref_frame] = INT_MAX;
     if (cpi->ref_frame_flags & flag_list[ref_frame]) {
-      setup_buffer_inter(cpi, x, tile, idx_list[ref_frame], ref_frame,
-                         block_size, mi_row, mi_col,
+      setup_buffer_inter(cpi, x, tile, get_ref_frame_idx(cpi, ref_frame),
+                         ref_frame, block_size, mi_row, mi_col,
                          frame_mv[NEARESTMV], frame_mv[NEARMV], yv12_mb);
     }
     frame_mv[NEWMV][ref_frame].as_int = INVALID_MV;
@@ -3243,14 +3204,14 @@
 
     x->skip = 0;
     this_mode = vp9_mode_order[mode_index].mode;
-    ref_frame = vp9_mode_order[mode_index].ref_frame;
-    second_ref_frame = vp9_mode_order[mode_index].second_ref_frame;
+    ref_frame = vp9_mode_order[mode_index].ref_frame[0];
+    second_ref_frame = vp9_mode_order[mode_index].ref_frame[1];
 
     // Look at the reference frame of the best mode so far and set the
     // skip mask to look at a subset of the remaining modes.
     if (mode_index > cpi->sf.mode_skip_start) {
       if (mode_index == (cpi->sf.mode_skip_start + 1)) {
-        switch (vp9_mode_order[best_mode_index].ref_frame) {
+        switch (vp9_mode_order[best_mode_index].ref_frame[0]) {
           case INTRA_FRAME:
             cpi->mode_skip_mask = 0;
             break;
@@ -3295,19 +3256,6 @@
     if (x->fast_ms > 2 && ref_frame != x->subblock_ref)
       continue;
 
-    if (cpi->sf.use_avoid_tested_higherror && bsize >= BLOCK_8X8) {
-      if (!(ref_frame_mask & (1 << ref_frame))) {
-        continue;
-      }
-      if (!(mode_mask & (1 << this_mode))) {
-        continue;
-      }
-      if (second_ref_frame != NONE
-          && !(ref_frame_mask & (1 << second_ref_frame))) {
-        continue;
-      }
-    }
-
     mbmi->ref_frame[0] = ref_frame;
     mbmi->ref_frame[1] = second_ref_frame;
 
@@ -3323,7 +3271,7 @@
     comp_pred = second_ref_frame > INTRA_FRAME;
     if (comp_pred) {
       if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_COMP_BESTINTRA)
-        if (vp9_mode_order[best_mode_index].ref_frame == INTRA_FRAME)
+        if (vp9_mode_order[best_mode_index].ref_frame[0] == INTRA_FRAME)
           continue;
       if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_COMP_REFMISMATCH)
         if (ref_frame != best_inter_ref_frame &&
@@ -3422,7 +3370,7 @@
       // one of the neighboring directional modes
       if ((cpi->sf.mode_search_skip_flags & FLAG_SKIP_INTRA_BESTINTER) &&
           (this_mode >= D45_PRED && this_mode <= TM_PRED)) {
-        if (vp9_mode_order[best_mode_index].ref_frame > INTRA_FRAME)
+        if (vp9_mode_order[best_mode_index].ref_frame[0] > INTRA_FRAME)
           continue;
       }
       mbmi->mode = this_mode;
@@ -3556,10 +3504,6 @@
         || distortion2 < mode_distortions[this_mode]) {
       mode_distortions[this_mode] = distortion2;
     }
-    if (frame_distortions[ref_frame] == -1
-        || distortion2 < frame_distortions[ref_frame]) {
-      frame_distortions[ref_frame] = distortion2;
-    }
 
     // Did this mode help.. i.e. is it the new best mode
     if (this_rd < best_rd || x->skip) {
@@ -3683,7 +3627,7 @@
   // If we used an estimate for the uv intra rd in the loop above...
   if (cpi->sf.use_uv_intra_rd_estimate) {
     // Do Intra UV best rd mode selection if best mode choice above was intra.
-    if (vp9_mode_order[best_mode_index].ref_frame == INTRA_FRAME) {
+    if (vp9_mode_order[best_mode_index].ref_frame[0] == INTRA_FRAME) {
       TX_SIZE uv_tx_size;
       *mbmi = best_mbmode;
       uv_tx_size = get_uv_tx_size(mbmi);
@@ -3699,7 +3643,7 @@
   // If we are using reference masking and the set mask flag is set then
   // create the reference frame mask.
   if (cpi->sf.reference_masking && cpi->set_ref_frame_mask)
-    cpi->ref_frame_mask = ~(1 << vp9_mode_order[best_mode_index].ref_frame);
+    cpi->ref_frame_mask = ~(1 << vp9_mode_order[best_mode_index].ref_frame[0]);
 
   // Flag all modes that have a distortion thats > 2x the best we found at
   // this level.
@@ -3712,14 +3656,6 @@
     }
   }
 
-  // Flag all ref frames that have a distortion thats > 2x the best we found at
-  // this level.
-  for (ref_frame = INTRA_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) {
-    if (frame_distortions[ref_frame] > 2 * *returndistortion) {
-      ctx->frames_with_high_error |= (1 << ref_frame);
-    }
-  }
-
   assert((cm->mcomp_filter_type == SWITCHABLE) ||
          (cm->mcomp_filter_type == best_mbmode.interp_filter) ||
          !is_inter_block(&best_mbmode));
@@ -3811,10 +3747,6 @@
   struct buf_2d yv12_mb[4][MAX_MB_PLANE];
   static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG,
                                     VP9_ALT_FLAG };
-  int idx_list[4] = {0,
-                     cpi->lst_fb_idx,
-                     cpi->gld_fb_idx,
-                     cpi->alt_fb_idx};
   int64_t best_rd = best_rd_so_far;
   int64_t best_yrd = best_rd_so_far;  // FIXME(rbultje) more precise
   int64_t best_tx_rd[TX_MODES];
@@ -3834,8 +3766,7 @@
   int64_t dist_uv[TX_SIZES];
   int skip_uv[TX_SIZES];
   MB_PREDICTION_MODE mode_uv[TX_SIZES] = { 0 };
-  int intra_cost_penalty = 20 * vp9_dc_quant(cpi->common.base_qindex,
-                                             cpi->common.y_dc_delta_q);
+  int intra_cost_penalty = 20 * vp9_dc_quant(cm->base_qindex, cm->y_dc_delta_q);
   int_mv seg_mvs[4][MAX_REF_FRAMES];
   b_mode_info best_bmodes[4];
   int best_skip2 = 0;
@@ -3865,8 +3796,8 @@
 
   for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) {
     if (cpi->ref_frame_flags & flag_list[ref_frame]) {
-      setup_buffer_inter(cpi, x, tile, idx_list[ref_frame], ref_frame,
-                         block_size, mi_row, mi_col,
+      setup_buffer_inter(cpi, x, tile, get_ref_frame_idx(cpi, ref_frame),
+                         ref_frame, block_size, mi_row, mi_col,
                          frame_mv[NEARESTMV], frame_mv[NEARMV],
                          yv12_mb);
     }
@@ -3892,14 +3823,14 @@
       tx_cache[i] = INT64_MAX;
 
     x->skip = 0;
-    ref_frame = vp9_ref_order[mode_index].ref_frame;
-    second_ref_frame = vp9_ref_order[mode_index].second_ref_frame;
+    ref_frame = vp9_ref_order[mode_index].ref_frame[0];
+    second_ref_frame = vp9_ref_order[mode_index].ref_frame[1];
 
     // Look at the reference frame of the best mode so far and set the
     // skip mask to look at a subset of the remaining modes.
     if (mode_index > 2 && cpi->sf.mode_skip_start < MAX_MODES) {
       if (mode_index == 3) {
-        switch (vp9_ref_order[best_mode_index].ref_frame) {
+        switch (vp9_ref_order[best_mode_index].ref_frame[0]) {
           case INTRA_FRAME:
             cpi->mode_skip_mask = 0;
             break;
@@ -3954,7 +3885,7 @@
     comp_pred = second_ref_frame > INTRA_FRAME;
     if (comp_pred) {
       if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_COMP_BESTINTRA)
-        if (vp9_ref_order[best_mode_index].ref_frame == INTRA_FRAME)
+        if (vp9_ref_order[best_mode_index].ref_frame[0] == INTRA_FRAME)
           continue;
       if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_COMP_REFMISMATCH)
         if (ref_frame != best_inter_ref_frame &&
@@ -3964,12 +3895,11 @@
 
     // TODO(jingning, jkoleszar): scaling reference frame not supported for
     // sub8x8 blocks.
-    if (ref_frame > 0 &&
-        vp9_is_scaled(&cpi->common.active_ref_scale[ref_frame - 1]))
+    if (ref_frame > 0 && vp9_is_scaled(&cm->frame_refs[ref_frame - 1].sf))
       continue;
 
     if (second_ref_frame > 0 &&
-        vp9_is_scaled(&cpi->common.active_ref_scale[second_ref_frame - 1]))
+        vp9_is_scaled(&cm->frame_refs[second_ref_frame - 1].sf))
       continue;
 
     set_scale_factors(cm, xd, ref_frame - 1, second_ref_frame - 1);
@@ -3978,7 +3908,7 @@
     // Evaluate all sub-pel filters irrespective of whether we can use
     // them for this frame.
     mbmi->interp_filter = cm->mcomp_filter_type;
-    vp9_setup_interp_filters(xd, mbmi->interp_filter, &cpi->common);
+    vp9_setup_interp_filters(xd, mbmi->interp_filter, cm);
 
     if (comp_pred) {
       if (!(cpi->ref_frame_flags & flag_list[second_ref_frame]))
@@ -4101,7 +4031,7 @@
             int newbest, rs;
             int64_t rs_rd;
             mbmi->interp_filter = switchable_filter_index;
-            vp9_setup_interp_filters(xd, mbmi->interp_filter, &cpi->common);
+            vp9_setup_interp_filters(xd, mbmi->interp_filter, cm);
 
             tmp_rd = rd_pick_best_mbsegmentation(cpi, x, tile,
                                                  &mbmi->ref_mvs[ref_frame][0],
@@ -4167,7 +4097,7 @@
 
       mbmi->interp_filter = (cm->mcomp_filter_type == SWITCHABLE ?
                              tmp_best_filter : cm->mcomp_filter_type);
-      vp9_setup_interp_filters(xd, mbmi->interp_filter, &cpi->common);
+      vp9_setup_interp_filters(xd, mbmi->interp_filter, cm);
       if (!pred_exists) {
         // Handles the special case when a filter that is not in the
         // switchable list (bilinear, 6-tap) is indicated at the frame level
@@ -4183,7 +4113,7 @@
         if (tmp_rd == INT64_MAX)
           continue;
       } else {
-        if (cpi->common.mcomp_filter_type == SWITCHABLE) {
+        if (cm->mcomp_filter_type == SWITCHABLE) {
           int rs = get_switchable_rate(x);
           tmp_best_rdu -= RDCOST(x->rdmult, x->rddiv, rs, 0);
         }
@@ -4201,13 +4131,12 @@
       rate2 += rate;
       distortion2 += distortion;
 
-      if (cpi->common.mcomp_filter_type == SWITCHABLE)
+      if (cm->mcomp_filter_type == SWITCHABLE)
         rate2 += get_switchable_rate(x);
 
       if (!mode_excluded)
-         mode_excluded = comp_pred
-             ? cpi->common.reference_mode == SINGLE_REFERENCE
-             : cpi->common.reference_mode == COMPOUND_REFERENCE;
+        mode_excluded = comp_pred ? cm->reference_mode == SINGLE_REFERENCE
+                                  : cm->reference_mode == COMPOUND_REFERENCE;
 
       compmode_cost = vp9_cost_bit(comp_mode_p, comp_pred);
 
@@ -4235,7 +4164,7 @@
       }
     }
 
-    if (cpi->common.reference_mode == REFERENCE_MODE_SELECT)
+    if (cm->reference_mode == REFERENCE_MODE_SELECT)
       rate2 += compmode_cost;
 
     // Estimate the reference frame signaling cost and add it
@@ -4346,7 +4275,7 @@
     if (!disable_skip && ref_frame != INTRA_FRAME) {
       int64_t single_rd, hybrid_rd, single_rate, hybrid_rate;
 
-      if (cpi->common.reference_mode == REFERENCE_MODE_SELECT) {
+      if (cm->reference_mode == REFERENCE_MODE_SELECT) {
         single_rate = rate2 - compmode_cost;
         hybrid_rate = rate2;
       } else {
@@ -4425,7 +4354,7 @@
   // If we used an estimate for the uv intra rd in the loop above...
   if (cpi->sf.use_uv_intra_rd_estimate) {
     // Do Intra UV best rd mode selection if best mode choice above was intra.
-    if (vp9_ref_order[best_mode_index].ref_frame == INTRA_FRAME) {
+    if (vp9_ref_order[best_mode_index].ref_frame[0] == INTRA_FRAME) {
       TX_SIZE uv_tx_size;
       *mbmi = best_mbmode;
       uv_tx_size = get_uv_tx_size(mbmi);
@@ -4440,7 +4369,7 @@
   // If we are using reference masking and the set mask flag is set then
   // create the reference frame mask.
   if (cpi->sf.reference_masking && cpi->set_ref_frame_mask)
-    cpi->ref_frame_mask = ~(1 << vp9_ref_order[best_mode_index].ref_frame);
+    cpi->ref_frame_mask = ~(1 << vp9_ref_order[best_mode_index].ref_frame[0]);
 
   if (best_rd == INT64_MAX && bsize < BLOCK_8X8) {
     *returnrate = INT_MAX;
diff --git a/vp9/encoder/vp9_segmentation.c b/vp9/encoder/vp9_segmentation.c
index 4568e7a..509717e 100644
--- a/vp9/encoder/vp9_segmentation.c
+++ b/vp9/encoder/vp9_segmentation.c
@@ -296,3 +296,12 @@
     vpx_memcpy(seg->tree_probs, no_pred_tree, sizeof(no_pred_tree));
   }
 }
+
+void vp9_reset_segment_features(struct segmentation *seg) {
+  // Set up default state for MB feature flags
+  seg->enabled = 0;
+  seg->update_map = 0;
+  seg->update_data = 0;
+  vpx_memset(seg->tree_probs, 255, sizeof(seg->tree_probs));
+  vp9_clearall_segfeatures(seg);
+}
diff --git a/vp9/encoder/vp9_segmentation.h b/vp9/encoder/vp9_segmentation.h
index 03f14ea..3c6eb70 100644
--- a/vp9/encoder/vp9_segmentation.h
+++ b/vp9/encoder/vp9_segmentation.h
@@ -43,4 +43,6 @@
 
 void vp9_choose_segmap_coding_method(VP9_COMP *cpi);
 
+void vp9_reset_segment_features(struct segmentation *seg);
+
 #endif  // VP9_ENCODER_VP9_SEGMENTATION_H_
diff --git a/vp9/encoder/x86/vp9_variance_avx2.c b/vp9/encoder/x86/vp9_variance_avx2.c
new file mode 100644
index 0000000..c9b90d5
--- /dev/null
+++ b/vp9/encoder/x86/vp9_variance_avx2.c
@@ -0,0 +1,157 @@
+/*
+ *  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 "./vpx_config.h"
+
+#include "vp9/encoder/vp9_variance.h"
+#include "vp9/common/vp9_pragmas.h"
+#include "vpx_ports/mem.h"
+
+typedef void (*get_var_avx2) (
+  const unsigned char *src_ptr,
+  int source_stride,
+  const unsigned char *ref_ptr,
+  int recon_stride,
+  unsigned int *SSE,
+  int *Sum
+);
+
+void vp9_get16x16var_avx2
+(
+  const unsigned char *src_ptr,
+  int source_stride,
+  const unsigned char *ref_ptr,
+  int recon_stride,
+  unsigned int *SSE,
+  int *Sum
+);
+
+void vp9_get32x32var_avx2
+(
+  const unsigned char *src_ptr,
+  int source_stride,
+  const unsigned char *ref_ptr,
+  int recon_stride,
+  unsigned int *SSE,
+  int *Sum
+);
+
+static void variance_avx2(const unsigned char *src_ptr, int  source_stride,
+                        const unsigned char *ref_ptr, int  recon_stride,
+                        int  w, int  h, unsigned int *sse, int *sum,
+                        get_var_avx2 var_fn, int block_size) {
+  unsigned int sse0;
+  int sum0;
+  int i, j;
+
+  *sse = 0;
+  *sum = 0;
+
+  for (i = 0; i < h; i += 16) {
+    for (j = 0; j < w; j += block_size) {
+      // processing 16 rows horizontally each call
+      var_fn(src_ptr + source_stride * i + j, source_stride,
+             ref_ptr + recon_stride * i + j, recon_stride, &sse0, &sum0);
+      *sse += sse0;
+      *sum += sum0;
+    }
+  }
+}
+
+unsigned int vp9_variance16x16_avx2
+(
+  const unsigned char *src_ptr,
+  int  source_stride,
+  const unsigned char *ref_ptr,
+  int  recon_stride,
+  unsigned int *sse) {
+  unsigned int var;
+  int avg;
+
+  variance_avx2(src_ptr, source_stride, ref_ptr, recon_stride, 16, 16,
+                &var, &avg, vp9_get16x16var_avx2, 16);
+  *sse = var;
+  return (var - (((unsigned int)avg * avg) >> 8));
+}
+
+unsigned int vp9_mse16x16_avx2(
+  const unsigned char *src_ptr,
+  int  source_stride,
+  const unsigned char *ref_ptr,
+  int  recon_stride,
+  unsigned int *sse) {
+  unsigned int sse0;
+  int sum0;
+  vp9_get16x16var_avx2(src_ptr, source_stride, ref_ptr, recon_stride, &sse0,
+                       &sum0);
+  *sse = sse0;
+  return sse0;
+}
+
+unsigned int vp9_variance32x32_avx2(const uint8_t *src_ptr,
+                                    int  source_stride,
+                                    const uint8_t *ref_ptr,
+                                    int  recon_stride,
+                                    unsigned int *sse) {
+  unsigned int var;
+  int avg;
+
+  // processing 32 elements vertically in parallel
+  variance_avx2(src_ptr, source_stride, ref_ptr, recon_stride, 32, 32,
+                &var, &avg, vp9_get32x32var_avx2, 32);
+  *sse = var;
+  return (var - (((int64_t)avg * avg) >> 10));
+}
+
+unsigned int vp9_variance32x16_avx2(const uint8_t *src_ptr,
+                                    int  source_stride,
+                                    const uint8_t *ref_ptr,
+                                    int  recon_stride,
+                                    unsigned int *sse) {
+  unsigned int var;
+  int avg;
+
+  // processing 32 elements vertically in parallel
+  variance_avx2(src_ptr, source_stride, ref_ptr, recon_stride, 32, 16,
+                &var, &avg, vp9_get32x32var_avx2, 32);
+  *sse = var;
+  return (var - (((int64_t)avg * avg) >> 9));
+}
+
+
+unsigned int vp9_variance64x64_avx2(const uint8_t *src_ptr,
+                                    int  source_stride,
+                                    const uint8_t *ref_ptr,
+                                    int  recon_stride,
+                                    unsigned int *sse) {
+  unsigned int var;
+  int avg;
+
+  // processing 32 elements vertically in parallel
+  variance_avx2(src_ptr, source_stride, ref_ptr, recon_stride, 64, 64,
+                &var, &avg, vp9_get32x32var_avx2, 32);
+  *sse = var;
+  return (var - (((int64_t)avg * avg) >> 12));
+}
+
+unsigned int vp9_variance64x32_avx2(const uint8_t *src_ptr,
+                                    int  source_stride,
+                                    const uint8_t *ref_ptr,
+                                    int  recon_stride,
+                                    unsigned int *sse) {
+  unsigned int var;
+  int avg;
+
+  // processing 32 elements vertically in parallel
+  variance_avx2(src_ptr, source_stride, ref_ptr, recon_stride, 64, 32,
+                &var, &avg, vp9_get32x32var_avx2, 32);
+
+  *sse = var;
+  return (var - (((int64_t)avg * avg) >> 11));
+}
diff --git a/vp9/encoder/x86/vp9_variance_impl_intrin_avx2.c b/vp9/encoder/x86/vp9_variance_impl_intrin_avx2.c
new file mode 100644
index 0000000..f992328
--- /dev/null
+++ b/vp9/encoder/x86/vp9_variance_impl_intrin_avx2.c
@@ -0,0 +1,213 @@
+/*
+ *  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 <immintrin.h>  // AVX2
+
+void vp9_get16x16var_avx2(const unsigned char *src_ptr,
+                          int source_stride,
+                          const unsigned char *ref_ptr,
+                          int recon_stride,
+                          unsigned int *SSE,
+                          int *Sum) {
+    __m256i src, src_expand_low, src_expand_high, ref, ref_expand_low;
+    __m256i ref_expand_high, madd_low, madd_high;
+    unsigned int i, src_2strides, ref_2strides;
+    __m256i zero_reg = _mm256_set1_epi16(0);
+    __m256i sum_ref_src = _mm256_set1_epi16(0);
+    __m256i madd_ref_src = _mm256_set1_epi16(0);
+
+    // processing two strides in a 256 bit register reducing the number
+    // of loop stride by half (comparing to the sse2 code)
+    src_2strides = source_stride << 1;
+    ref_2strides = recon_stride << 1;
+    for (i = 0; i < 8; i++) {
+        src = _mm256_castsi128_si256(
+              _mm_loadu_si128((__m128i const *) (src_ptr)));
+        src = _mm256_inserti128_si256(src,
+              _mm_loadu_si128((__m128i const *)(src_ptr+source_stride)), 1);
+
+        ref =_mm256_castsi128_si256(
+             _mm_loadu_si128((__m128i const *) (ref_ptr)));
+        ref = _mm256_inserti128_si256(ref,
+              _mm_loadu_si128((__m128i const *)(ref_ptr+recon_stride)), 1);
+
+        // expanding to 16 bit each lane
+        src_expand_low = _mm256_unpacklo_epi8(src, zero_reg);
+        src_expand_high = _mm256_unpackhi_epi8(src, zero_reg);
+
+        ref_expand_low = _mm256_unpacklo_epi8(ref, zero_reg);
+        ref_expand_high = _mm256_unpackhi_epi8(ref, zero_reg);
+
+        // src-ref
+        src_expand_low = _mm256_sub_epi16(src_expand_low, ref_expand_low);
+        src_expand_high = _mm256_sub_epi16(src_expand_high, ref_expand_high);
+
+        // madd low (src - ref)
+        madd_low = _mm256_madd_epi16(src_expand_low, src_expand_low);
+
+        // add high to low
+        src_expand_low = _mm256_add_epi16(src_expand_low, src_expand_high);
+
+        // madd high (src - ref)
+        madd_high = _mm256_madd_epi16(src_expand_high, src_expand_high);
+
+        sum_ref_src = _mm256_add_epi16(sum_ref_src, src_expand_low);
+
+        // add high to low
+        madd_ref_src = _mm256_add_epi32(madd_ref_src,
+                       _mm256_add_epi32(madd_low, madd_high));
+
+        src_ptr+= src_2strides;
+        ref_ptr+= ref_2strides;
+    }
+
+    {
+        __m128i sum_res, madd_res;
+        __m128i expand_sum_low, expand_sum_high, expand_sum;
+        __m128i expand_madd_low, expand_madd_high, expand_madd;
+        __m128i ex_expand_sum_low, ex_expand_sum_high, ex_expand_sum;
+
+        // extract the low lane and add it to the high lane
+        sum_res = _mm_add_epi16(_mm256_castsi256_si128(sum_ref_src),
+                                _mm256_extractf128_si256(sum_ref_src, 1));
+
+        madd_res = _mm_add_epi32(_mm256_castsi256_si128(madd_ref_src),
+                                 _mm256_extractf128_si256(madd_ref_src, 1));
+
+        // padding each 2 bytes with another 2 zeroed bytes
+        expand_sum_low = _mm_unpacklo_epi16(_mm256_castsi256_si128(zero_reg),
+                                            sum_res);
+        expand_sum_high = _mm_unpackhi_epi16(_mm256_castsi256_si128(zero_reg),
+                                             sum_res);
+
+        // shifting the sign 16 bits right
+        expand_sum_low = _mm_srai_epi32(expand_sum_low, 16);
+        expand_sum_high = _mm_srai_epi32(expand_sum_high, 16);
+
+        expand_sum = _mm_add_epi32(expand_sum_low, expand_sum_high);
+
+        // expand each 32 bits of the madd result to 64 bits
+        expand_madd_low = _mm_unpacklo_epi32(madd_res,
+                          _mm256_castsi256_si128(zero_reg));
+        expand_madd_high = _mm_unpackhi_epi32(madd_res,
+                           _mm256_castsi256_si128(zero_reg));
+
+        expand_madd = _mm_add_epi32(expand_madd_low, expand_madd_high);
+
+        ex_expand_sum_low = _mm_unpacklo_epi32(expand_sum,
+                            _mm256_castsi256_si128(zero_reg));
+        ex_expand_sum_high = _mm_unpackhi_epi32(expand_sum,
+                             _mm256_castsi256_si128(zero_reg));
+
+        ex_expand_sum = _mm_add_epi32(ex_expand_sum_low, ex_expand_sum_high);
+
+        // shift 8 bytes eight
+        madd_res = _mm_srli_si128(expand_madd, 8);
+        sum_res = _mm_srli_si128(ex_expand_sum, 8);
+
+        madd_res = _mm_add_epi32(madd_res, expand_madd);
+        sum_res = _mm_add_epi32(sum_res, ex_expand_sum);
+
+        *((int*)SSE)= _mm_cvtsi128_si32(madd_res);
+
+        *((int*)Sum)= _mm_cvtsi128_si32(sum_res);
+    }
+}
+
+void vp9_get32x32var_avx2(const unsigned char *src_ptr,
+                          int source_stride,
+                          const unsigned char *ref_ptr,
+                          int recon_stride,
+                          unsigned int *SSE,
+                          int *Sum) {
+    __m256i src, src_expand_low, src_expand_high, ref, ref_expand_low;
+    __m256i ref_expand_high, madd_low, madd_high;
+    unsigned int i;
+    __m256i zero_reg = _mm256_set1_epi16(0);
+    __m256i sum_ref_src = _mm256_set1_epi16(0);
+    __m256i madd_ref_src = _mm256_set1_epi16(0);
+
+    // processing 32 elements in parallel
+    for (i = 0; i < 16; i++) {
+       src = _mm256_loadu_si256((__m256i const *) (src_ptr));
+
+       ref = _mm256_loadu_si256((__m256i const *) (ref_ptr));
+
+       // expanding to 16 bit each lane
+       src_expand_low = _mm256_unpacklo_epi8(src, zero_reg);
+       src_expand_high = _mm256_unpackhi_epi8(src, zero_reg);
+
+       ref_expand_low = _mm256_unpacklo_epi8(ref, zero_reg);
+       ref_expand_high = _mm256_unpackhi_epi8(ref, zero_reg);
+
+       // src-ref
+       src_expand_low = _mm256_sub_epi16(src_expand_low, ref_expand_low);
+       src_expand_high = _mm256_sub_epi16(src_expand_high, ref_expand_high);
+
+       // madd low (src - ref)
+       madd_low = _mm256_madd_epi16(src_expand_low, src_expand_low);
+
+       // add high to low
+       src_expand_low = _mm256_add_epi16(src_expand_low, src_expand_high);
+
+       // madd high (src - ref)
+       madd_high = _mm256_madd_epi16(src_expand_high, src_expand_high);
+
+       sum_ref_src = _mm256_add_epi16(sum_ref_src, src_expand_low);
+
+       // add high to low
+       madd_ref_src = _mm256_add_epi32(madd_ref_src,
+                      _mm256_add_epi32(madd_low, madd_high));
+
+       src_ptr+= source_stride;
+       ref_ptr+= recon_stride;
+    }
+
+    {
+      __m256i expand_sum_low, expand_sum_high, expand_sum;
+      __m256i expand_madd_low, expand_madd_high, expand_madd;
+      __m256i ex_expand_sum_low, ex_expand_sum_high, ex_expand_sum;
+
+      // padding each 2 bytes with another 2 zeroed bytes
+      expand_sum_low = _mm256_unpacklo_epi16(zero_reg, sum_ref_src);
+      expand_sum_high = _mm256_unpackhi_epi16(zero_reg, sum_ref_src);
+
+      // shifting the sign 16 bits right
+      expand_sum_low = _mm256_srai_epi32(expand_sum_low, 16);
+      expand_sum_high = _mm256_srai_epi32(expand_sum_high, 16);
+
+      expand_sum = _mm256_add_epi32(expand_sum_low, expand_sum_high);
+
+      // expand each 32 bits of the madd result to 64 bits
+      expand_madd_low = _mm256_unpacklo_epi32(madd_ref_src, zero_reg);
+      expand_madd_high = _mm256_unpackhi_epi32(madd_ref_src, zero_reg);
+
+      expand_madd = _mm256_add_epi32(expand_madd_low, expand_madd_high);
+
+      ex_expand_sum_low = _mm256_unpacklo_epi32(expand_sum, zero_reg);
+      ex_expand_sum_high = _mm256_unpackhi_epi32(expand_sum, zero_reg);
+
+      ex_expand_sum = _mm256_add_epi32(ex_expand_sum_low, ex_expand_sum_high);
+
+      // shift 8 bytes eight
+      madd_ref_src = _mm256_srli_si256(expand_madd, 8);
+      sum_ref_src = _mm256_srli_si256(ex_expand_sum, 8);
+
+      madd_ref_src = _mm256_add_epi32(madd_ref_src, expand_madd);
+      sum_ref_src = _mm256_add_epi32(sum_ref_src, ex_expand_sum);
+
+      // extract the low lane and the high lane and add the results
+      *((int*)SSE)= _mm_cvtsi128_si32(_mm256_castsi256_si128(madd_ref_src)) +
+      _mm_cvtsi128_si32(_mm256_extractf128_si256(madd_ref_src, 1));
+
+      *((int*)Sum)= _mm_cvtsi128_si32(_mm256_castsi256_si128(sum_ref_src)) +
+      _mm_cvtsi128_si32(_mm256_extractf128_si256(sum_ref_src, 1));
+    }
+}
diff --git a/vp9/vp9cx.mk b/vp9/vp9cx.mk
index 9114a30..0d79346 100644
--- a/vp9/vp9cx.mk
+++ b/vp9/vp9cx.mk
@@ -81,6 +81,7 @@
 VP9_CX_SRCS-$(HAVE_MMX) += encoder/x86/vp9_variance_impl_mmx.asm
 VP9_CX_SRCS-$(HAVE_MMX) += encoder/x86/vp9_sad_mmx.asm
 VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_variance_impl_sse2.asm
+VP9_CX_SRCS-$(HAVE_AVX2) += encoder/x86/vp9_variance_impl_intrin_avx2.c
 VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_sad4d_sse2.asm
 VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_subpel_variance_impl_sse2.asm
 VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_temporal_filter_apply_sse2.asm
@@ -91,6 +92,7 @@
 VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_sad_sse2.asm
 VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_subtract_sse2.asm
 VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_variance_sse2.c
+VP9_CX_SRCS-$(HAVE_AVX2) += encoder/x86/vp9_variance_avx2.c
 VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_subpel_variance.asm
 endif
 
diff --git a/vp9_spatial_scalable_encoder.c b/vp9_spatial_scalable_encoder.c
index a727f50..b637331 100644
--- a/vp9_spatial_scalable_encoder.c
+++ b/vp9_spatial_scalable_encoder.c
@@ -79,7 +79,9 @@
   struct VpxInputContext input_ctx;
 } AppInput;
 
-void usage_exit(const char *exec_name) {
+static const char *exec_name;
+
+void usage_exit() {
   fprintf(stderr, "Usage: %s <options> input_filename output_filename\n",
           exec_name);
   fprintf(stderr, "Options:\n");
@@ -95,12 +97,6 @@
   exit(EXIT_FAILURE);
 }
 
-static int create_dummy_frame(vpx_image_t *img) {
-  const size_t buf_size = img->w * img->h * 3 / 2;
-  memset(img->planes[0], 129, buf_size);
-  return 1;
-}
-
 static void parse_command_line(int argc, const char **argv_,
                                AppInput *app_input, SvcContext *svc_ctx,
                                vpx_codec_enc_cfg_t *enc_cfg) {
@@ -170,7 +166,7 @@
       die("Error: Unrecognized option %s\n", *argi);
 
   if (argv[0] == NULL || argv[1] == 0) {
-    usage_exit(argv_[0]);
+    usage_exit();
   }
   app_input->input_ctx.filename = argv[0];
   app_input->output_filename = argv[1];
@@ -210,6 +206,7 @@
 
   memset(&svc_ctx, 0, sizeof(svc_ctx));
   svc_ctx.log_print = 1;
+  exec_name = argv[0];
   parse_command_line(argc, argv, &app_input, &svc_ctx, &enc_cfg);
 
   // Allocate image buffer
@@ -260,8 +257,16 @@
   fclose(app_input.input_ctx.file);
   if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
 
-  // rewrite the output file headers with the actual frame count
+  // rewrite the output file headers with the actual frame count, and
+  // resolution of the highest layer
   if (!fseek(outfile, 0, SEEK_SET)) {
+    // get resolution of highest layer
+    if (VPX_CODEC_OK != vpx_svc_get_layer_resolution(&svc_ctx,
+                                                     svc_ctx.spatial_layers - 1,
+                                                     &enc_cfg.g_w,
+                                                     &enc_cfg.g_h)) {
+      die("Failed to get output resolution");
+    }
     ivf_write_file_header(outfile, &enc_cfg, VP9_FOURCC, frame_cnt);
   }
   fclose(outfile);
diff --git a/vpx/exports_enc b/vpx/exports_enc
index 1d9340c..99b1bfa 100644
--- a/vpx/exports_enc
+++ b/vpx/exports_enc
@@ -20,3 +20,4 @@
 text vpx_svc_set_options
 text vpx_svc_set_quantizers
 text vpx_svc_set_scale_factors
+text vpx_svc_get_layer_resolution
diff --git a/vpxenc.c b/vpxenc.c
index d0ed9b5..4c933ce 100644
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -26,7 +26,6 @@
 
 #include "third_party/libyuv/include/libyuv/scale.h"
 #include "./args.h"
-#include "./ivfdec.h"
 #include "./ivfenc.h"
 
 #if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
@@ -126,13 +125,19 @@
   return !shortread;
 }
 
-int file_is_y4m(FILE *infile, y4m_input *y4m, const char detect[4]) {
+int file_is_y4m(const char detect[4]) {
   if (memcmp(detect, "YUV4", 4) == 0) {
     return 1;
   }
   return 0;
 }
 
+int fourcc_is_ivf(const char detect[4]) {
+  if (memcmp(detect, "DKIF", 4) == 0) {
+    return 1;
+  }
+  return 0;
+}
 
 /* Murmur hash derived from public domain reference implementation at
  *   http:// sites.google.com/site/murmurhash/
@@ -1044,7 +1049,7 @@
   input->detect.position = 0;
 
   if (input->detect.buf_read == 4
-      && file_is_y4m(input->file, &input->y4m, input->detect.buf)) {
+      && file_is_y4m(input->detect.buf)) {
     if (y4m_input_open(&input->y4m, input->file, input->detect.buf, 4,
                        input->only_i420) >= 0) {
       input->file_type = FILE_TYPE_Y4M;
@@ -1055,7 +1060,7 @@
       input->use_i420 = 0;
     } else
       fatal("Unsupported Y4M stream.");
-  } else if (input->detect.buf_read == 4 && file_is_ivf(input)) {
+  } else if (input->detect.buf_read == 4 && fourcc_is_ivf(input->detect.buf)) {
     fatal("IVF is not supported as input.");
   } else {
     input->file_type = FILE_TYPE_RAW;
diff --git a/warnings.c b/warnings.c
index f76d706..a9c7d04 100644
--- a/warnings.c
+++ b/warnings.c
@@ -71,14 +71,6 @@
   return c == 'y';
 }
 
-static void check_lag_in_frames_realtime_deadline(
-    int lag_in_frames,
-    int deadline,
-    struct WarningList *warning_list) {
-  if (deadline == VPX_DL_REALTIME && lag_in_frames != 0)
-    add_warning(lag_in_frames_with_realtime, warning_list);
-}
-
 static void check_quantizer(int min_q, int max_q,
                             struct WarningList *warning_list) {
   const int lossless = min_q == 0 && max_q == 0;
@@ -88,7 +80,7 @@
 
 void check_encoder_config(int disable_prompt,
                           const struct VpxEncoderConfig *global_config,
-                          const struct vpx_codec_enc_cfg *stream_config) {
+                          struct vpx_codec_enc_cfg *stream_config) {
   int num_warnings = 0;
   struct WarningListNode *warning = NULL;
   struct WarningList warning_list = {0};
@@ -96,9 +88,9 @@
   check_quantizer(stream_config->rc_min_quantizer,
                   stream_config->rc_max_quantizer,
                   &warning_list);
-  check_lag_in_frames_realtime_deadline(stream_config->g_lag_in_frames,
-                                        global_config->deadline,
-                                        &warning_list);
+
+  if (global_config->deadline == VPX_DL_REALTIME)
+    stream_config->g_lag_in_frames = 0;
 
   /* Count and print warnings. */
   for (warning = warning_list.warning_node;
diff --git a/warnings.h b/warnings.h
index ac3a4b6..90b34c8 100644
--- a/warnings.h
+++ b/warnings.h
@@ -20,6 +20,6 @@
  */
 void check_encoder_config(int disable_prompt,
                           const struct VpxEncoderConfig *global_config,
-                          const struct vpx_codec_enc_cfg *stream_config);
+                          struct vpx_codec_enc_cfg *stream_config);
 
 #endif  // WARNINGS_H_