Merge "scan order table lookup  same for encoder and decoder"
diff --git a/examples.mk b/examples.mk
index 3324fd9..36d20df 100644
--- a/examples.mk
+++ b/examples.mk
@@ -25,6 +25,7 @@
 vpxdec.SRCS                 += args.c args.h
 vpxdec.SRCS                 += ivfdec.c ivfdec.h
 vpxdec.SRCS                 += tools_common.c tools_common.h
+vpxdec.SRCS                 += webmdec.c webmdec.h
 vpxdec.SRCS                 += nestegg/halloc/halloc.h
 vpxdec.SRCS                 += nestegg/halloc/src/align.h
 vpxdec.SRCS                 += nestegg/halloc/src/halloc.c
diff --git a/tools_common.h b/tools_common.h
index 353f90a..7500523 100644
--- a/tools_common.h
+++ b/tools_common.h
@@ -92,11 +92,11 @@
   off_t length;
   struct FileTypeDetectionBuffer detect;
   enum VideoFileType file_type;
-  unsigned int width;
-  unsigned int height;
+  uint32_t width;
+  uint32_t height;
   int use_i420;
   int only_i420;
-  unsigned int fourcc;
+  uint32_t fourcc;
   struct VpxRational framerate;
 #if CONFIG_ENCODERS
   y4m_input y4m;
diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c
index 4b60cfd..1c773b7 100644
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -3808,11 +3808,22 @@
 
     /* Setup background Q adjustment for error resilient mode.
      * For multi-layer encodes only enable this for the base layer.
-     */
+     * Reduce loop filter to reduce "dot" artifacts that can occur for repeated
+     * loop filtering on ZEROMV_LASTREF blocks.
+     * For now reducing it to -32, only for resolutions above CIF and
+     * #temporal_layers < 3 (artifact is hard to see at low spatial resolution
+     * and/or high #temporal layers).
+    */
     if (cpi->cyclic_refresh_mode_enabled)
     {
+      int delta_loop_filter = 0;
+      if (cm->Width > 352 && cm->Height > 288 &&
+          cpi->oxcf.number_of_layers < 3)
+      {
+        delta_loop_filter = -32;
+      }
       if (cpi->current_layer==0)
-        cyclic_background_refresh(cpi, Q, 0);
+        cyclic_background_refresh(cpi, Q, delta_loop_filter);
       else
         disable_segmentation(cpi);
     }
diff --git a/vp9/common/vp9_common_data.c b/vp9/common/vp9_common_data.c
index 466074b..388f38d 100644
--- a/vp9/common/vp9_common_data.c
+++ b/vp9/common/vp9_common_data.c
@@ -123,8 +123,6 @@
   TX_32X32,  // TX_MODE_SELECT
 };
 
-
-
 const BLOCK_SIZE ss_size_lookup[BLOCK_SIZES][2][2] = {
 //  ss_x == 0    ss_x == 0        ss_x == 1      ss_x == 1
 //  ss_y == 0    ss_y == 1        ss_y == 0      ss_y == 1
@@ -144,23 +142,23 @@
 };
 
 // Generates 4 bit field in which each bit set to 1 represents
-// a blocksize partition  1111 means we split 8x8, 16x16, 32x32
-// and 64x64.  0001 means we just split the 64x64...
+// a blocksize partition  1111 means we split 64x64, 32x32, 16x16
+// and 8x8.  1000 means we just split the 64x64 to 32x32
 const struct {
   PARTITION_CONTEXT above;
   PARTITION_CONTEXT left;
 } partition_context_lookup[BLOCK_SIZES]= {
-  {15, 15},  // 4X4
-  {15,  7},  // 4X8
-  {7,  15},  // 8X4
-  {7,   7},  // 8X8
-  {7,   3},  // 8X16
-  {3,   7},  // 16X8
-  {3,   3},  // 16X16
-  {3,   1},  // 16X32
-  {1,   3},  // 32X16
-  {1,   1},  // 32X32
-  {1,   0},  // 32X64
-  {0,   1},  // 64X32
-  {0,   0},  // 64X64
+  {15, 15},  // 4X4   - {0b1111, 0b1111}
+  {15, 14},  // 4X8   - {0b1111, 0b1110}
+  {14, 15},  // 8X4   - {0b1110, 0b1111}
+  {14, 14},  // 8X8   - {0b1110, 0b1110}
+  {14, 12},  // 8X16  - {0b1110, 0b1100}
+  {12, 14},  // 16X8  - {0b1100, 0b1110}
+  {12, 12},  // 16X16 - {0b1100, 0b1100}
+  {12, 8 },  // 16X32 - {0b1100, 0b1000}
+  {8,  12},  // 32X16 - {0b1000, 0b1100}
+  {8,  8 },  // 32X32 - {0b1000, 0b1000}
+  {8,  0 },  // 32X64 - {0b1000, 0b0000}
+  {0,  8 },  // 64X32 - {0b0000, 0b1000}
+  {0,  0 },  // 64X64 - {0b0000, 0b0000}
 };
diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h
index 943fcdc..fb959cb 100644
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -303,43 +303,40 @@
 static INLINE void update_partition_context(
     PARTITION_CONTEXT *above_seg_context,
     PARTITION_CONTEXT left_seg_context[8],
-    int mi_row, int mi_col,
-    BLOCK_SIZE sb_type,
-    BLOCK_SIZE sb_size) {
-  PARTITION_CONTEXT *above_ctx = above_seg_context + mi_col;
-  PARTITION_CONTEXT *left_ctx = left_seg_context + (mi_row & MI_MASK);
+    int mi_row, int mi_col, BLOCK_SIZE subsize, BLOCK_SIZE bsize) {
+  PARTITION_CONTEXT *const above_ctx = above_seg_context + mi_col;
+  PARTITION_CONTEXT *const left_ctx = left_seg_context + (mi_row & MI_MASK);
 
-  const int bsl = b_width_log2(sb_size), bs = (1 << bsl) / 2;
+  // num_4x4_blocks_wide_lookup[bsize] / 2
+  const int bs = num_8x8_blocks_wide_lookup[bsize];
 
   // update the partition context at the end notes. set partition bits
   // of block sizes larger than the current one to be one, and partition
   // bits of smaller block sizes to be zero.
-  vpx_memset(above_ctx, partition_context_lookup[sb_type].above, bs);
-  vpx_memset(left_ctx, partition_context_lookup[sb_type].left, bs);
+  vpx_memset(above_ctx, partition_context_lookup[subsize].above, bs);
+  vpx_memset(left_ctx, partition_context_lookup[subsize].left, bs);
 }
 
 static INLINE int partition_plane_context(
     const PARTITION_CONTEXT *above_seg_context,
     const PARTITION_CONTEXT left_seg_context[8],
-    int mi_row, int mi_col,
-    BLOCK_SIZE sb_type) {
+    int mi_row, int mi_col, BLOCK_SIZE bsize) {
   const PARTITION_CONTEXT *above_ctx = above_seg_context + mi_col;
   const PARTITION_CONTEXT *left_ctx = left_seg_context + (mi_row & MI_MASK);
 
-  int bsl = mi_width_log2(sb_type), bs = 1 << bsl;
+  const int bsl = mi_width_log2(bsize);
+  const int bs = 1 << bsl;
   int above = 0, left = 0, i;
-  int boffset = mi_width_log2(BLOCK_64X64) - bsl;
 
-  assert(mi_width_log2(sb_type) == mi_height_log2(sb_type));
+  assert(mi_width_log2(bsize) == mi_height_log2(bsize));
   assert(bsl >= 0);
-  assert(boffset >= 0);
 
   for (i = 0; i < bs; i++) {
     above |= above_ctx[i];
     left |= left_ctx[i];
   }
-  above = (above & (1 << boffset)) > 0;
-  left  = (left & (1 << boffset)) > 0;
+  above = (above & bs) > 0;
+  left  = (left & bs) > 0;
 
   return (left * 2 + above) + bsl * PARTITION_PLOFFSET;
 }
diff --git a/vp9/common/vp9_reconinter.c b/vp9/common/vp9_reconinter.c
index 7cc66c8..3add81b 100644
--- a/vp9/common/vp9_reconinter.c
+++ b/vp9/common/vp9_reconinter.c
@@ -20,25 +20,6 @@
 #include "vp9/common/vp9_reconinter.h"
 #include "vp9/common/vp9_reconintra.h"
 
-void vp9_setup_interp_filters(MACROBLOCKD *xd,
-                              INTERPOLATION_TYPE mcomp_filter_type,
-                              VP9_COMMON *cm) {
-  if (xd->mi_8x8 && xd->mi_8x8[0]) {
-    MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
-
-    set_scale_factors(xd, mbmi->ref_frame[0] - LAST_FRAME,
-                          mbmi->ref_frame[1] - LAST_FRAME,
-                          cm->active_ref_scale);
-  } else {
-    set_scale_factors(xd, -1, -1, cm->active_ref_scale);
-  }
-
-  xd->subpix.filter_x = xd->subpix.filter_y =
-      vp9_get_filter_kernel(mcomp_filter_type == SWITCHABLE ?
-                               EIGHTTAP : mcomp_filter_type);
-
-  assert(((intptr_t)xd->subpix.filter_x & 0xff) == 0);
-}
 
 static void inter_predictor(const uint8_t *src, int src_stride,
                             uint8_t *dst, int dst_stride,
diff --git a/vp9/common/vp9_reconinter.h b/vp9/common/vp9_reconinter.h
index 2c8a6e4..b328754 100644
--- a/vp9/common/vp9_reconinter.h
+++ b/vp9/common/vp9_reconinter.h
@@ -24,10 +24,6 @@
 void vp9_build_inter_predictors_sb(MACROBLOCKD *xd, int mi_row, int mi_col,
                                    BLOCK_SIZE bsize);
 
-void vp9_setup_interp_filters(MACROBLOCKD *xd,
-                              INTERPOLATION_TYPE filter,
-                              VP9_COMMON *cm);
-
 void vp9_build_inter_predictor(const uint8_t *src, int src_stride,
                                uint8_t *dst, int dst_stride,
                                const MV *mv_q3,
diff --git a/vp9/common/x86/vp9_subpixel_8t_ssse3.asm b/vp9/common/x86/vp9_subpixel_8t_ssse3.asm
index 7a5cca0..dbc17ec 100644
--- a/vp9/common/x86/vp9_subpixel_8t_ssse3.asm
+++ b/vp9/common/x86/vp9_subpixel_8t_ssse3.asm
@@ -11,17 +11,6 @@
 
 %include "vpx_ports/x86_abi_support.asm"
 
-;/************************************************************************************
-; Notes: filter_block1d_h6 applies a 6 tap filter horizontally to the input pixels. The
-; input pixel array has output_height rows. This routine assumes that output_height is an
-; even number. This function handles 8 pixels in horizontal direction, calculating ONE
-; rows each iteration to take advantage of the 128 bits operations.
-;
-; This is an implementation of some of the SSE optimizations first seen in ffvp8
-;
-;*************************************************************************************/
-
-
 %macro VERTx4 1
     mov         rdx, arg(5)                 ;filter ptr
     mov         rsi, arg(0)                 ;src_ptr
@@ -81,11 +70,14 @@
     pmaddubsw   xmm4, k4k5
     pmaddubsw   xmm6, k6k7
 
+    movdqa      xmm1, xmm2
     paddsw      xmm0, xmm6
-    paddsw      xmm0, xmm2
+    pmaxsw      xmm2, xmm4
+    pminsw      xmm4, xmm1
     paddsw      xmm0, xmm4
-    paddsw      xmm0, krd
+    paddsw      xmm0, xmm2
 
+    paddsw      xmm0, krd
     psraw       xmm0, 7
     packuswb    xmm0, xmm0
 
@@ -538,14 +530,22 @@
     movdqa      %2,   %1
     pshufb      %1,   [GLOBAL(shuf_t0t1)]
     pshufb      %2,   [GLOBAL(shuf_t2t3)]
-    pmaddubsw   %1,   xmm6
-    pmaddubsw   %2,   xmm7
+    pmaddubsw   %1,   k0k1k4k5
+    pmaddubsw   %2,   k2k3k6k7
 
-    paddsw      %1,   %2
-    movdqa      %2,   %1
+    movdqa      xmm4, %1
+    movdqa      xmm5, %2
+    psrldq      %1,   8
     psrldq      %2,   8
-    paddsw      %1,   %2
-    paddsw      %1,   xmm5
+    movdqa      xmm6, xmm5
+
+    paddsw      xmm4, %2
+    pmaxsw      xmm5, %1
+    pminsw      %1, xmm6
+    paddsw      %1, xmm4
+    paddsw      %1, xmm5
+
+    paddsw      %1,   krd
     psraw       %1,   7
     packuswb    %1,   %1
 %endm
@@ -565,6 +565,10 @@
     pshufhw     xmm7, xmm7, 11111111b       ;k2_k3_k6_k7
     pshufd      xmm5, xmm5, 0               ;rounding
 
+    movdqa      k0k1k4k5, xmm6
+    movdqa      k2k3k6k7, xmm7
+    movdqa      krd, xmm5
+
     movsxd      rax, dword ptr arg(1)       ;src_pixels_per_line
     movsxd      rdx, dword ptr arg(3)       ;output_pitch
     movsxd      rcx, dword ptr arg(4)       ;output_height
@@ -826,8 +830,15 @@
     push        rdi
     ; end prolog
 
+    ALIGN_STACK 16, rax
+    sub         rsp, 16 * 3
+    %define k0k1k4k5 [rsp + 16 * 0]
+    %define k2k3k6k7 [rsp + 16 * 1]
+    %define krd      [rsp + 16 * 2]
+
     HORIZx4 0
 
+    add rsp, 16 * 3
     ; begin epilog
     pop rdi
     pop rsi
@@ -932,8 +943,15 @@
     push        rdi
     ; end prolog
 
+    ALIGN_STACK 16, rax
+    sub         rsp, 16 * 3
+    %define k0k1k4k5 [rsp + 16 * 0]
+    %define k2k3k6k7 [rsp + 16 * 1]
+    %define krd      [rsp + 16 * 2]
+
     HORIZx4 1
 
+    add rsp, 16 * 3
     ; begin epilog
     pop rdi
     pop rsi
diff --git a/vp9/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c
index 1f4fb66..dbcae76 100644
--- a/vp9/decoder/vp9_decodeframe.c
+++ b/vp9/decoder/vp9_decodeframe.c
@@ -241,16 +241,13 @@
 }
 
 static void inverse_transform_block(MACROBLOCKD* xd, int plane, int block,
-                                    TX_SIZE tx_size, int x, int y) {
+                                    TX_SIZE tx_size, uint8_t *dst, int stride) {
   struct macroblockd_plane *const pd = &xd->plane[plane];
   const int eob = pd->eobs[block];
   if (eob > 0) {
     TX_TYPE tx_type;
     const int plane_type = pd->plane_type;
-    const int stride = pd->dst.stride;
     int16_t *const dqcoeff = BLOCK_OFFSET(pd->dqcoeff, block);
-    uint8_t *const dst = &pd->dst.buf[4 * y * stride + 4 * x];
-
     switch (tx_size) {
       case TX_4X4:
         tx_type = get_tx_type_4x4(plane_type, xd, block);
@@ -322,7 +319,7 @@
   if (!mi->mbmi.skip_coeff) {
     vp9_decode_block_tokens(cm, xd, plane, block, plane_bsize, x, y, tx_size,
                             args->r, args->token_cache);
-    inverse_transform_block(xd, plane, block, tx_size, x, y);
+    inverse_transform_block(xd, plane, block, tx_size, dst, pd->dst.stride);
   }
 }
 
@@ -340,13 +337,15 @@
   struct inter_args *args = arg;
   VP9_COMMON *const cm = args->cm;
   MACROBLOCKD *const xd = args->xd;
+  struct macroblockd_plane *const pd = &xd->plane[plane];
   int x, y;
   txfrm_block_to_raster_xy(plane_bsize, tx_size, block, &x, &y);
-
   *args->eobtotal += vp9_decode_block_tokens(cm, xd, plane, block,
                                              plane_bsize, x, y, tx_size,
                                              args->r, args->token_cache);
-  inverse_transform_block(xd, plane, block, tx_size, x, y);
+  inverse_transform_block(xd, plane, block, tx_size,
+                          &pd->dst.buf[4 * y * pd->dst.stride + 4 * x],
+                          pd->dst.stride);
 }
 
 static void set_offsets(VP9_COMMON *const cm, MACROBLOCKD *const xd,
diff --git a/vp9/encoder/vp9_encodemb.c b/vp9/encoder/vp9_encodemb.c
index 0d089ce..0e1523b 100644
--- a/vp9/encoder/vp9_encodemb.c
+++ b/vp9/encoder/vp9_encodemb.c
@@ -25,6 +25,26 @@
 #include "vp9/encoder/vp9_rdopt.h"
 #include "vp9/encoder/vp9_tokenize.h"
 
+void vp9_setup_interp_filters(MACROBLOCKD *xd,
+                              INTERPOLATION_TYPE mcomp_filter_type,
+                              VP9_COMMON *cm) {
+  if (xd->mi_8x8 && xd->mi_8x8[0]) {
+    MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
+
+    set_scale_factors(xd, mbmi->ref_frame[0] - LAST_FRAME,
+                          mbmi->ref_frame[1] - LAST_FRAME,
+                          cm->active_ref_scale);
+  } else {
+    set_scale_factors(xd, -1, -1, cm->active_ref_scale);
+  }
+
+  xd->subpix.filter_x = xd->subpix.filter_y =
+      vp9_get_filter_kernel(mcomp_filter_type == SWITCHABLE ?
+                               EIGHTTAP : mcomp_filter_type);
+
+  assert(((intptr_t)xd->subpix.filter_x & 0xff) == 0);
+}
+
 void vp9_subtract_block_c(int rows, int cols,
                           int16_t *diff_ptr, ptrdiff_t diff_stride,
                           const uint8_t *src_ptr, ptrdiff_t src_stride,
diff --git a/vp9/encoder/vp9_encodemb.h b/vp9/encoder/vp9_encodemb.h
index 8fbc4a0..7be6621 100644
--- a/vp9/encoder/vp9_encodemb.h
+++ b/vp9/encoder/vp9_encodemb.h
@@ -54,5 +54,7 @@
 void vp9_encode_intra_block_uv(MACROBLOCK *x, BLOCK_SIZE bsize);
 
 int vp9_encode_intra(MACROBLOCK *x, int use_16x16_pred);
-
+void vp9_setup_interp_filters(MACROBLOCKD *xd,
+                              INTERPOLATION_TYPE mcomp_filter_type,
+                              VP9_COMMON *cm);
 #endif  // VP9_ENCODER_VP9_ENCODEMB_H_
diff --git a/vp9/encoder/vp9_encodemv.c b/vp9/encoder/vp9_encodemv.c
index 030ca64..7e838c9 100644
--- a/vp9/encoder/vp9_encodemv.c
+++ b/vp9/encoder/vp9_encodemv.c
@@ -126,20 +126,15 @@
 
 static int update_mv(vp9_writer *w, const unsigned int ct[2], vp9_prob *cur_p,
                      vp9_prob upd_p) {
-  const vp9_prob new_p = get_binary_prob(ct[0], ct[1]);
-  vp9_prob mod_p = new_p | 1;
-  const int cur_b = cost_branch256(ct, *cur_p);
-  const int mod_b = cost_branch256(ct, mod_p);
-  const int cost = 7 * 256 + (vp9_cost_one(upd_p) - vp9_cost_zero(upd_p));
-  if (cur_b - mod_b > cost) {
-    *cur_p = mod_p;
-    vp9_write(w, 1, upd_p);
-    vp9_write_literal(w, mod_p >> 1, 7);
-    return 1;
-  } else {
-    vp9_write(w, 0, upd_p);
-    return 0;
+  const vp9_prob new_p = get_binary_prob(ct[0], ct[1]) | 1;
+  const int update = cost_branch256(ct, *cur_p) + vp9_cost_zero(upd_p) >
+                     cost_branch256(ct, new_p) + vp9_cost_one(upd_p) + 7 * 256;
+  vp9_write(w, update, upd_p);
+  if (update) {
+    *cur_p = new_p;
+    vp9_write_literal(w, new_p >> 1, 7);
   }
+  return update;
 }
 
 static void counts_to_nmv_context(
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index 63be00e..5d37f83 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -2636,6 +2636,16 @@
   vpx_free(second_pred);
 }
 
+static INLINE void restore_dst_buf(MACROBLOCKD *xd,
+                                   uint8_t *orig_dst[MAX_MB_PLANE],
+                                   int orig_dst_stride[MAX_MB_PLANE]) {
+  int i;
+  for (i = 0; i < MAX_MB_PLANE; i++) {
+    xd->plane[i].dst.buf = orig_dst[i];
+    xd->plane[i].dst.stride = orig_dst_stride[i];
+  }
+}
+
 static int64_t handle_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
                                  const TileInfo *const tile,
                                  BLOCK_SIZE bsize,
@@ -2787,6 +2797,7 @@
   if (is_comp_pred)
     intpel_mv &= (mbmi->mv[1].as_mv.row & 15) == 0 &&
         (mbmi->mv[1].as_mv.col & 15) == 0;
+
   // Search for best switchable filter by checking the variance of
   // pred error irrespective of whether the filter will be used
   if (cm->mcomp_filter_type != BILINEAR) {
@@ -2826,10 +2837,7 @@
               (cm->mcomp_filter_type != SWITCHABLE &&
                (cm->mcomp_filter_type == mbmi->interp_filter ||
                 (i == 0 && intpel_mv)))) {
-            for (j = 0; j < MAX_MB_PLANE; j++) {
-              xd->plane[j].dst.buf = orig_dst[j];
-              xd->plane[j].dst.stride = orig_dst_stride[j];
-            }
+            restore_dst_buf(xd, orig_dst, orig_dst_stride);
           } else {
             for (j = 0; j < MAX_MB_PLANE; j++) {
               xd->plane[j].dst.buf = tmp_buf + j * 64 * 64;
@@ -2853,10 +2861,7 @@
         }
         if (i == 0 && cpi->sf.use_rd_breakout && ref_best_rd < INT64_MAX) {
           if (rd / 2 > ref_best_rd) {
-            for (i = 0; i < MAX_MB_PLANE; i++) {
-              xd->plane[i].dst.buf = orig_dst[i];
-              xd->plane[i].dst.stride = orig_dst_stride[i];
-            }
+            restore_dst_buf(xd, orig_dst, orig_dst_stride);
             return INT64_MAX;
           }
         }
@@ -2875,11 +2880,7 @@
           pred_exists = 1;
         }
       }
-
-      for (i = 0; i < MAX_MB_PLANE; i++) {
-        xd->plane[i].dst.buf = orig_dst[i];
-        xd->plane[i].dst.stride = orig_dst_stride[i];
-      }
+      restore_dst_buf(xd, orig_dst, orig_dst_stride);
     }
   }
   // Set the appropriate filter
@@ -2911,10 +2912,7 @@
     // if current pred_error modeled rd is substantially more than the best
     // so far, do not bother doing full rd
     if (rd / 2 > ref_best_rd) {
-      for (i = 0; i < MAX_MB_PLANE; i++) {
-        xd->plane[i].dst.buf = orig_dst[i];
-        xd->plane[i].dst.stride = orig_dst_stride[i];
-      }
+      restore_dst_buf(xd, orig_dst, orig_dst_stride);
       return INT64_MAX;
     }
   }
@@ -3017,10 +3015,7 @@
     if (*rate_y == INT_MAX) {
       *rate2 = INT_MAX;
       *distortion = INT64_MAX;
-      for (i = 0; i < MAX_MB_PLANE; i++) {
-        xd->plane[i].dst.buf = orig_dst[i];
-        xd->plane[i].dst.stride = orig_dst_stride[i];
-      }
+      restore_dst_buf(xd, orig_dst, orig_dst_stride);
       return INT64_MAX;
     }
 
@@ -3035,10 +3030,7 @@
     if (*rate_uv == INT_MAX) {
       *rate2 = INT_MAX;
       *distortion = INT64_MAX;
-      for (i = 0; i < MAX_MB_PLANE; i++) {
-        xd->plane[i].dst.buf = orig_dst[i];
-        xd->plane[i].dst.stride = orig_dst_stride[i];
-      }
+      restore_dst_buf(xd, orig_dst, orig_dst_stride);
       return INT64_MAX;
     }
 
@@ -3048,11 +3040,7 @@
     *skippable = skippable_y && skippable_uv;
   }
 
-  for (i = 0; i < MAX_MB_PLANE; i++) {
-    xd->plane[i].dst.buf = orig_dst[i];
-    xd->plane[i].dst.stride = orig_dst_stride[i];
-  }
-
+  restore_dst_buf(xd, orig_dst, orig_dst_stride);
   return this_rd;  // if 0, this will be re-calculated by caller
 }
 
diff --git a/vp9/encoder/vp9_sad_c.c b/vp9/encoder/vp9_sad_c.c
index 42ddb21..55d595b 100644
--- a/vp9/encoder/vp9_sad_c.c
+++ b/vp9/encoder/vp9_sad_c.c
@@ -10,11 +10,11 @@
 
 
 #include <stdlib.h>
-#include "vp9/common/vp9_sadmxn.h"
-#include "vp9/encoder/vp9_variance.h"
-#include "./vpx_config.h"
-#include "vpx/vpx_integer.h"
 #include "./vp9_rtcd.h"
+#include "./vpx_config.h"
+#include "vp9/encoder/vp9_sadmxn.h"
+#include "vp9/encoder/vp9_variance.h"
+#include "vpx/vpx_integer.h"
 
 #define sad_mxn_func(m, n) \
 unsigned int vp9_sad##m##x##n##_c(const uint8_t *src_ptr, \
diff --git a/vp9/common/vp9_sadmxn.h b/vp9/encoder/vp9_sadmxn.h
similarity index 100%
rename from vp9/common/vp9_sadmxn.h
rename to vp9/encoder/vp9_sadmxn.h
diff --git a/vp9/encoder/vp9_subexp.c b/vp9/encoder/vp9_subexp.c
index 387fc90..f31e568 100644
--- a/vp9/encoder/vp9_subexp.c
+++ b/vp9/encoder/vp9_subexp.c
@@ -14,7 +14,6 @@
 #include "vp9/encoder/vp9_boolhuff.h"
 #include "vp9/encoder/vp9_treewriter.h"
 
-#define vp9_cost_upd  ((int)(vp9_cost_one(upd) - vp9_cost_zero(upd)) >> 8)
 #define vp9_cost_upd256  ((int)(vp9_cost_one(upd) - vp9_cost_zero(upd)))
 
 static int update_bits[255];
diff --git a/vp9/encoder/vp9_treewriter.h b/vp9/encoder/vp9_treewriter.h
index eeda5cd..41d1bfb 100644
--- a/vp9/encoder/vp9_treewriter.h
+++ b/vp9/encoder/vp9_treewriter.h
@@ -19,31 +19,20 @@
 
 #include "vp9/encoder/vp9_boolhuff.h"       /* for now */
 
-
 #define vp9_write_prob(w, v) vp9_write_literal((w), (v), 8)
 
-/* Approximate length of an encoded bool in 256ths of a bit at given prob */
+#define vp9_cost_zero(prob) (vp9_prob_cost[prob])
 
-#define vp9_cost_zero(x) (vp9_prob_cost[x])
-#define vp9_cost_one(x) vp9_cost_zero(vp9_complement(x))
+#define vp9_cost_one(prob) vp9_cost_zero(vp9_complement(prob))
 
-#define vp9_cost_bit(x, b) vp9_cost_zero((b) ? vp9_complement(x) : (x))
+#define vp9_cost_bit(prob, bit) vp9_cost_zero((bit) ? vp9_complement(prob) \
+                                                    : (prob))
 
-/* VP8BC version is scaled by 2^20 rather than 2^8; see bool_coder.h */
-
-
-/* Both of these return bits, not scaled bits. */
 static INLINE unsigned int cost_branch256(const unsigned int ct[2],
                                           vp9_prob p) {
   return ct[0] * vp9_cost_zero(p) + ct[1] * vp9_cost_one(p);
 }
 
-static INLINE unsigned int cost_branch(const unsigned int ct[2],
-                                       vp9_prob p) {
-  return cost_branch256(ct, p) >> 8;
-}
-
-
 static INLINE void treed_write(vp9_writer *w,
                                vp9_tree tree, const vp9_prob *probs,
                                int bits, int len) {
diff --git a/vp9/vp9_common.mk b/vp9/vp9_common.mk
index 57ede0f..c566765 100644
--- a/vp9/vp9_common.mk
+++ b/vp9/vp9_common.mk
@@ -45,7 +45,6 @@
 VP9_COMMON_SRCS-yes += common/vp9_reconintra.h
 VP9_COMMON_SRCS-yes += common/vp9_rtcd.c
 VP9_COMMON_SRCS-yes += common/vp9_rtcd_defs.sh
-VP9_COMMON_SRCS-yes += common/vp9_sadmxn.h
 VP9_COMMON_SRCS-yes += common/vp9_scale.h
 VP9_COMMON_SRCS-yes += common/vp9_scale.c
 VP9_COMMON_SRCS-yes += common/vp9_seg_common.h
diff --git a/vp9/vp9cx.mk b/vp9/vp9cx.mk
index b594779..bd13518 100644
--- a/vp9/vp9cx.mk
+++ b/vp9/vp9cx.mk
@@ -44,6 +44,7 @@
 VP9_CX_SRCS-yes += encoder/vp9_quantize.h
 VP9_CX_SRCS-yes += encoder/vp9_ratectrl.h
 VP9_CX_SRCS-yes += encoder/vp9_rdopt.h
+VP9_CX_SRCS-yes += encoder/vp9_sadmxn.h
 VP9_CX_SRCS-yes += encoder/vp9_tokenize.h
 VP9_CX_SRCS-yes += encoder/vp9_treewriter.h
 VP9_CX_SRCS-yes += encoder/vp9_variance.h
diff --git a/vpxdec.c b/vpxdec.c
index 6508992..dc2eec8 100644
--- a/vpxdec.c
+++ b/vpxdec.c
@@ -15,6 +15,9 @@
 #include <string.h>
 #include <limits.h>
 
+#include "third_party/libyuv/include/libyuv/scale.h"
+
+#include "./args.h"
 #include "./ivfdec.h"
 
 #define VPX_CODEC_DISABLE_COMPAT 1
@@ -27,20 +30,19 @@
 #endif
 
 #if CONFIG_MD5
-#include "md5_utils.h"
+#include "./md5_utils.h"
 #endif
 
 #include "./tools_common.h"
-#include "nestegg/include/nestegg/nestegg.h"
-#include "third_party/libyuv/include/libyuv/scale.h"
+#include "./webmdec.h"
 
 static const char *exec_name;
 
 static const struct {
   char const *name;
   const vpx_codec_iface_t *(*iface)(void);
-  unsigned int             fourcc;
-  unsigned int             fourcc_mask;
+  uint32_t fourcc;
+  uint32_t fourcc_mask;
 } ifaces[] = {
 #if CONFIG_VP8_DECODER
   {"vp8",  vpx_codec_vp8_dx,   VP8_FOURCC_MASK, 0x00FFFFFF},
@@ -50,7 +52,11 @@
 #endif
 };
 
-#include "args.h"
+struct VpxDecInputContext {
+  struct VpxInputContext *vpx_input_ctx;
+  struct WebmInputContext *webm_ctx;
+};
+
 static const arg_def_t looparg = ARG_DEF(NULL, "loops", 1,
                                           "Number of times to decode the file");
 static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1,
@@ -162,15 +168,6 @@
   exit(EXIT_FAILURE);
 }
 
-struct VpxDecInputContext {
-  nestegg *nestegg_ctx;
-  nestegg_packet *pkt;
-  unsigned int chunk;
-  unsigned int chunks;
-  unsigned int video_track;
-  struct VpxInputContext *vpx_input_ctx;
-};
-
 static int read_frame(struct VpxDecInputContext *input,
                       uint8_t **buf,
                       size_t *bytes_in_buffer,
@@ -180,30 +177,8 @@
   FILE *infile = input->vpx_input_ctx->file;
   enum VideoFileType kind = input->vpx_input_ctx->file_type;
   if (kind == FILE_TYPE_WEBM) {
-    if (input->chunk >= input->chunks) {
-      unsigned int track;
-
-      do {
-        /* End of this packet, get another. */
-        if (input->pkt)
-          nestegg_free_packet(input->pkt);
-
-        if (nestegg_read_packet(input->nestegg_ctx, &input->pkt) <= 0
-            || nestegg_packet_track(input->pkt, &track))
-          return 1;
-
-      } while (track != input->video_track);
-
-      if (nestegg_packet_count(input->pkt, &input->chunks))
-        return 1;
-      input->chunk = 0;
-    }
-
-    if (nestegg_packet_data(input->pkt, input->chunk, buf, bytes_in_buffer))
-      return 1;
-    input->chunk++;
-
-    return 0;
+    return webm_read_frame(input->webm_ctx,
+                           buf, bytes_in_buffer, buffer_size);
   } else if (kind == FILE_TYPE_RAW) {
     if (fread(raw_hdr, RAW_FRAME_HDR_SZ, 1, infile) != 1) {
       if (!feof(infile))
@@ -333,161 +308,12 @@
   return is_raw;
 }
 
-
-static int
-nestegg_read_cb(void *buffer, size_t length, void *userdata) {
-  FILE *f = userdata;
-
-  if (fread(buffer, 1, length, f) < length) {
-    if (ferror(f))
-      return -1;
-    if (feof(f))
-      return 0;
-  }
-  return 1;
-}
-
-
-static int
-nestegg_seek_cb(int64_t offset, int whence, void *userdata) {
-  switch (whence) {
-    case NESTEGG_SEEK_SET:
-      whence = SEEK_SET;
-      break;
-    case NESTEGG_SEEK_CUR:
-      whence = SEEK_CUR;
-      break;
-    case NESTEGG_SEEK_END:
-      whence = SEEK_END;
-      break;
-  };
-  return fseek(userdata, (long)offset, whence) ? -1 : 0;
-}
-
-
-static int64_t
-nestegg_tell_cb(void *userdata) {
-  return ftell(userdata);
-}
-
-
-static void
-nestegg_log_cb(nestegg *context, unsigned int severity, char const *format,
-               ...) {
-  va_list ap;
-
-  va_start(ap, format);
-  vfprintf(stderr, format, ap);
-  fprintf(stderr, "\n");
-  va_end(ap);
-}
-
-
-static int
-webm_guess_framerate(struct VpxDecInputContext *input) {
-  unsigned int i;
-  uint64_t     tstamp = 0;
-
-  /* Check to see if we can seek before we parse any data. */
-  if (nestegg_track_seek(input->nestegg_ctx, input->video_track, 0)) {
-    warn("WARNING: Failed to guess framerate (no Cues), set to 30fps.\n");
-    input->vpx_input_ctx->framerate.numerator = 30;
-    input->vpx_input_ctx->framerate.denominator  = 1;
-    return 0;
-  }
-
-  /* Guess the framerate. Read up to 1 second, or 50 video packets,
-   * whichever comes first.
-   */
-  for (i = 0; tstamp < 1000000000 && i < 50;) {
-    nestegg_packet *pkt;
-    unsigned int track;
-
-    if (nestegg_read_packet(input->nestegg_ctx, &pkt) <= 0)
-      break;
-
-    nestegg_packet_track(pkt, &track);
-    if (track == input->video_track) {
-      nestegg_packet_tstamp(pkt, &tstamp);
-      i++;
-    }
-
-    nestegg_free_packet(pkt);
-  }
-
-  if (nestegg_track_seek(input->nestegg_ctx, input->video_track, 0))
-    goto fail;
-
-  input->vpx_input_ctx->framerate.numerator = (i - 1) * 1000000;
-  input->vpx_input_ctx->framerate.denominator = (int)(tstamp / 1000);
-  return 0;
-fail:
-  nestegg_destroy(input->nestegg_ctx);
-  input->nestegg_ctx = NULL;
-  rewind(input->vpx_input_ctx->file);
-  return 1;
-}
-
-
-static int
-file_is_webm(struct VpxDecInputContext *input) {
-  unsigned int i, n;
-  int track_type = -1;
-  int codec_id;
-
-  nestegg_io io = {nestegg_read_cb, nestegg_seek_cb, nestegg_tell_cb, 0};
-  nestegg_video_params params;
-
-  io.userdata = input->vpx_input_ctx->file;
-  if (nestegg_init(&input->nestegg_ctx, io, NULL))
-    goto fail;
-
-  if (nestegg_track_count(input->nestegg_ctx, &n))
-    goto fail;
-
-  for (i = 0; i < n; i++) {
-    track_type = nestegg_track_type(input->nestegg_ctx, i);
-
-    if (track_type == NESTEGG_TRACK_VIDEO)
-      break;
-    else if (track_type < 0)
-      goto fail;
-  }
-
-  codec_id = nestegg_track_codec_id(input->nestegg_ctx, i);
-  if (codec_id == NESTEGG_CODEC_VP8) {
-    input->vpx_input_ctx->fourcc = VP8_FOURCC_MASK;
-  } else if (codec_id == NESTEGG_CODEC_VP9) {
-    input->vpx_input_ctx->fourcc = VP9_FOURCC_MASK;
-  } else {
-    fprintf(stderr, "Not VPx video, quitting.\n");
-    exit(1);
-  }
-
-  input->video_track = i;
-
-  if (nestegg_track_video_params(input->nestegg_ctx, i, &params))
-    goto fail;
-
-  input->vpx_input_ctx->framerate.denominator = 0;
-  input->vpx_input_ctx->framerate.numerator = 0;
-  input->vpx_input_ctx->width = params.width;
-  input->vpx_input_ctx->height = params.height;
-  return 1;
-fail:
-  input->nestegg_ctx = NULL;
-  rewind(input->vpx_input_ctx->file);
-  return 0;
-}
-
-
 void show_progress(int frame_in, int frame_out, unsigned long dx_time) {
   fprintf(stderr, "%d decoded frames/%d showed frames in %lu us (%.2f fps)\r",
           frame_in, frame_out, dx_time,
           (float)frame_out * 1000000.0 / (float)dx_time);
 }
 
-
 void generate_filename(const char *pattern, char *out, size_t q_len,
                        unsigned int d_w, unsigned int d_h,
                        unsigned int frame_in) {
@@ -606,7 +432,9 @@
 
   struct VpxDecInputContext input = {0};
   struct VpxInputContext vpx_input_ctx = {0};
+  struct WebmInputContext webm_ctx = {0};
   input.vpx_input_ctx = &vpx_input_ctx;
+  input.webm_ctx = &webm_ctx;
 
   /* Parse command line */
   exec_name = argv_[0];
@@ -748,7 +576,7 @@
   input.vpx_input_ctx->file = infile;
   if (file_is_ivf(input.vpx_input_ctx))
     input.vpx_input_ctx->file_type = FILE_TYPE_IVF;
-  else if (file_is_webm(&input))
+  else if (file_is_webm(input.webm_ctx, input.vpx_input_ctx))
     input.vpx_input_ctx->file_type = FILE_TYPE_WEBM;
   else if (file_is_raw(input.vpx_input_ctx))
     input.vpx_input_ctx->file_type = FILE_TYPE_RAW;
@@ -792,7 +620,7 @@
     }
 
     if (vpx_input_ctx.file_type == FILE_TYPE_WEBM)
-      if (webm_guess_framerate(&input)) {
+      if (webm_guess_framerate(input.webm_ctx, input.vpx_input_ctx)) {
         fprintf(stderr, "Failed to guess framerate -- error parsing "
                 "webm file?\n");
         return EXIT_FAILURE;
@@ -1036,10 +864,11 @@
   if (single_file && !noblit)
     out_close(out, outfile, do_md5);
 
-  if (input.nestegg_ctx)
-    nestegg_destroy(input.nestegg_ctx);
-  if (input.vpx_input_ctx->file_type != FILE_TYPE_WEBM)
+  if (input.vpx_input_ctx->file_type == FILE_TYPE_WEBM)
+    webm_free(input.webm_ctx);
+  else
     free(buf);
+
   fclose(infile);
   free(argv);
 
diff --git a/webmdec.c b/webmdec.c
new file mode 100644
index 0000000..4bf7c7e
--- /dev/null
+++ b/webmdec.c
@@ -0,0 +1,193 @@
+/*
+ *  Copyright (c) 2013 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 "./webmdec.h"
+
+#include <stdarg.h>
+
+#include "nestegg/include/nestegg/nestegg.h"
+
+static int nestegg_read_cb(void *buffer, size_t length, void *userdata) {
+  FILE *f = userdata;
+
+  if (fread(buffer, 1, length, f) < length) {
+    if (ferror(f))
+      return -1;
+    if (feof(f))
+      return 0;
+  }
+  return 1;
+}
+
+static int nestegg_seek_cb(int64_t offset, int whence, void *userdata) {
+  switch (whence) {
+    case NESTEGG_SEEK_SET:
+      whence = SEEK_SET;
+      break;
+    case NESTEGG_SEEK_CUR:
+      whence = SEEK_CUR;
+      break;
+    case NESTEGG_SEEK_END:
+      whence = SEEK_END;
+      break;
+  };
+  return fseek(userdata, (int32_t)offset, whence) ? -1 : 0;
+}
+
+static int64_t nestegg_tell_cb(void *userdata) {
+  return ftell(userdata);
+}
+
+static void nestegg_log_cb(nestegg *context,
+                           unsigned int severity,
+                           char const *format, ...) {
+  va_list ap;
+  va_start(ap, format);
+  vfprintf(stderr, format, ap);
+  fprintf(stderr, "\n");
+  va_end(ap);
+}
+
+int file_is_webm(struct WebmInputContext *webm_ctx,
+                 struct VpxInputContext *vpx_ctx) {
+  uint32_t i, n;
+  int track_type = -1;
+  int codec_id;
+
+  nestegg_io io = {nestegg_read_cb, nestegg_seek_cb, nestegg_tell_cb, 0};
+  nestegg_video_params params;
+
+  io.userdata = vpx_ctx->file;
+  if (nestegg_init(&webm_ctx->nestegg_ctx, io, NULL))
+    goto fail;
+
+  if (nestegg_track_count(webm_ctx->nestegg_ctx, &n))
+    goto fail;
+
+  for (i = 0; i < n; i++) {
+    track_type = nestegg_track_type(webm_ctx->nestegg_ctx, i);
+
+    if (track_type == NESTEGG_TRACK_VIDEO)
+      break;
+    else if (track_type < 0)
+      goto fail;
+  }
+
+  codec_id = nestegg_track_codec_id(webm_ctx->nestegg_ctx, i);
+  if (codec_id == NESTEGG_CODEC_VP8) {
+    vpx_ctx->fourcc = VP8_FOURCC_MASK;
+  } else if (codec_id == NESTEGG_CODEC_VP9) {
+    vpx_ctx->fourcc = VP9_FOURCC_MASK;
+  } else {
+    fatal("Not VPx video, quitting.\n");
+  }
+
+  webm_ctx->video_track = i;
+
+  if (nestegg_track_video_params(webm_ctx->nestegg_ctx, i, &params))
+    goto fail;
+
+  vpx_ctx->framerate.denominator = 0;
+  vpx_ctx->framerate.numerator = 0;
+  vpx_ctx->width = params.width;
+  vpx_ctx->height = params.height;
+
+  return 1;
+
+ fail:
+  webm_ctx->nestegg_ctx = NULL;
+  rewind(vpx_ctx->file);
+
+  return 0;
+}
+
+int webm_read_frame(struct WebmInputContext *webm_ctx,
+                    uint8_t **buffer,
+                    size_t *bytes_in_buffer,
+                    size_t *buffer_size) {
+  if (webm_ctx->chunk >= webm_ctx->chunks) {
+    uint32_t track;
+
+    do {
+      /* End of this packet, get another. */
+      if (webm_ctx->pkt)
+        nestegg_free_packet(webm_ctx->pkt);
+
+      if (nestegg_read_packet(webm_ctx->nestegg_ctx, &webm_ctx->pkt) <= 0 ||
+          nestegg_packet_track(webm_ctx->pkt, &track)) {
+        return 1;
+      }
+    } while (track != webm_ctx->video_track);
+
+    if (nestegg_packet_count(webm_ctx->pkt, &webm_ctx->chunks))
+      return 1;
+
+    webm_ctx->chunk = 0;
+  }
+
+  if (nestegg_packet_data(webm_ctx->pkt, webm_ctx->chunk,
+                          buffer, bytes_in_buffer)) {
+    return 1;
+  }
+
+  webm_ctx->chunk++;
+  return 0;
+}
+
+int webm_guess_framerate(struct WebmInputContext *webm_ctx,
+                         struct VpxInputContext *vpx_ctx) {
+  uint32_t i;
+  uint64_t tstamp = 0;
+
+  /* Check to see if we can seek before we parse any data. */
+  if (nestegg_track_seek(webm_ctx->nestegg_ctx, webm_ctx->video_track, 0)) {
+    warn("Failed to guess framerate (no Cues), set to 30fps.\n");
+    vpx_ctx->framerate.numerator = 30;
+    vpx_ctx->framerate.denominator  = 1;
+    return 0;
+  }
+
+  /* Guess the framerate. Read up to 1 second, or 50 video packets,
+   * whichever comes first.
+   */
+  for (i = 0; tstamp < 1000000000 && i < 50;) {
+    nestegg_packet *pkt;
+    uint32_t track;
+
+    if (nestegg_read_packet(webm_ctx->nestegg_ctx, &pkt) <= 0)
+      break;
+
+    nestegg_packet_track(pkt, &track);
+    if (track == webm_ctx->video_track) {
+      nestegg_packet_tstamp(pkt, &tstamp);
+      ++i;
+    }
+
+    nestegg_free_packet(pkt);
+  }
+
+  if (nestegg_track_seek(webm_ctx->nestegg_ctx, webm_ctx->video_track, 0))
+    goto fail;
+
+  vpx_ctx->framerate.numerator = (i - 1) * 1000000;
+  vpx_ctx->framerate.denominator = (int)(tstamp / 1000);
+  return 0;
+
+ fail:
+  nestegg_destroy(webm_ctx->nestegg_ctx);
+  webm_ctx->nestegg_ctx = NULL;
+  rewind(vpx_ctx->file);
+  return 1;
+}
+
+void webm_free(struct WebmInputContext *webm_ctx) {
+  if (webm_ctx && webm_ctx->nestegg_ctx)
+    nestegg_destroy(webm_ctx->nestegg_ctx);
+}
diff --git a/webmdec.h b/webmdec.h
new file mode 100644
index 0000000..002fbe6
--- /dev/null
+++ b/webmdec.h
@@ -0,0 +1,40 @@
+/*
+ *  Copyright (c) 2013 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.
+ */
+#ifndef WEBMDEC_H_
+#define WEBMDEC_H_
+
+#include "./tools_common.h"
+
+struct nestegg;
+struct nestegg_packet;
+struct VpxInputContext;
+
+struct WebmInputContext {
+  uint32_t chunk;
+  uint32_t chunks;
+  uint32_t video_track;
+  struct nestegg *nestegg_ctx;
+  struct nestegg_packet *pkt;
+};
+
+int file_is_webm(struct WebmInputContext *webm_ctx,
+                 struct VpxInputContext *vpx_ctx);
+
+int webm_read_frame(struct WebmInputContext *webm_ctx,
+                    uint8_t **buffer,
+                    size_t *bytes_in_buffer,
+                    size_t *buffer_size);
+
+int webm_guess_framerate(struct WebmInputContext *webm_ctx,
+                         struct VpxInputContext *vpx_ctx);
+
+void webm_free(struct WebmInputContext *webm_ctx);
+
+#endif  // WEBMDEC_H_