Merge "vp9: fix peek_si for version==0"
diff --git a/test/convolve_test.cc b/test/convolve_test.cc
index fd2bd36..93d3b01 100644
--- a/test/convolve_test.cc
+++ b/test/convolve_test.cc
@@ -22,8 +22,8 @@
 }
 
 namespace {
-typedef void (*convolve_fn_t)(const uint8_t *src, int src_stride,
-                              uint8_t *dst, int dst_stride,
+typedef void (*convolve_fn_t)(const uint8_t *src, ptrdiff_t src_stride,
+                              uint8_t *dst, ptrdiff_t dst_stride,
                               const int16_t *filter_x, int filter_x_stride,
                               const int16_t *filter_y, int filter_y_stride,
                               int w, int h);
@@ -211,7 +211,7 @@
 
   virtual void SetUp() {
     UUT_ = GET_PARAM(2);
-    /* Set up guard blocks for an inner block cetered in the outer block */
+    /* Set up guard blocks for an inner block centered in the outer block */
     for (int i = 0; i < kOutputBufferSize; ++i) {
       if (IsIndexInBorder(i))
         output_[i] = 255;
@@ -546,4 +546,26 @@
     make_tuple(32, 64, &convolve8_ssse3),
     make_tuple(64, 64, &convolve8_ssse3)));
 #endif
+
+#if HAVE_NEON
+const ConvolveFunctions convolve8_neon(
+    vp9_convolve8_horiz_neon, vp9_convolve8_avg_horiz_c,
+    vp9_convolve8_vert_neon, vp9_convolve8_avg_vert_c,
+    vp9_convolve8_c, vp9_convolve8_avg_c);
+
+INSTANTIATE_TEST_CASE_P(NEON, ConvolveTest, ::testing::Values(
+    make_tuple(4, 4, &convolve8_neon),
+    make_tuple(8, 4, &convolve8_neon),
+    make_tuple(4, 8, &convolve8_neon),
+    make_tuple(8, 8, &convolve8_neon),
+    make_tuple(16, 8, &convolve8_neon),
+    make_tuple(8, 16, &convolve8_neon),
+    make_tuple(16, 16, &convolve8_neon),
+    make_tuple(32, 16, &convolve8_neon),
+    make_tuple(16, 32, &convolve8_neon),
+    make_tuple(32, 32, &convolve8_neon),
+    make_tuple(64, 32, &convolve8_neon),
+    make_tuple(32, 64, &convolve8_neon),
+    make_tuple(64, 64, &convolve8_neon)));
+#endif
 }  // namespace
diff --git a/vp9/common/arm/neon/vp9_convolve8_neon.asm b/vp9/common/arm/neon/vp9_convolve8_neon.asm
new file mode 100644
index 0000000..842c73c
--- /dev/null
+++ b/vp9/common/arm/neon/vp9_convolve8_neon.asm
@@ -0,0 +1,250 @@
+;
+;  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.
+;
+
+
+    ; These functions are only valid when:
+    ; x_step_q4 == 16
+    ; w%4 == 0
+    ; h%4 == 0
+    ; taps == 8
+    ; VP9_FILTER_WEIGHT == 128
+    ; VP9_FILTER_SHIFT == 7
+
+    EXPORT  |vp9_convolve8_horiz_neon|
+    EXPORT  |vp9_convolve8_vert_neon|
+    IMPORT  |vp9_convolve8_horiz_c|
+    IMPORT  |vp9_convolve8_vert_c|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+    ; Multiply and accumulate by q0
+    MACRO
+    MULTIPLY_BY_Q0 $dst, $src0, $src1, $src2, $src3, $src4, $src5, $src6, $src7
+    vmull.s16 $dst, $src0, d0[0]
+    vmlal.s16 $dst, $src1, d0[1]
+    vmlal.s16 $dst, $src2, d0[2]
+    vmlal.s16 $dst, $src3, d0[3]
+    vmlal.s16 $dst, $src4, d1[0]
+    vmlal.s16 $dst, $src5, d1[1]
+    vmlal.s16 $dst, $src6, d1[2]
+    vmlal.s16 $dst, $src7, d1[3]
+    MEND
+
+; r0    const uint8_t *src
+; r1    int src_stride
+; r2    uint8_t *dst
+; r3    int dst_stride
+; sp[]const int16_t *filter_x
+; sp[]int x_step_q4
+; sp[]const int16_t *filter_y ; unused
+; sp[]int y_step_q4           ; unused
+; sp[]int w
+; sp[]int h
+
+|vp9_convolve8_horiz_neon| PROC
+    push            {r4-r10, lr}
+
+    sub             r0, r0, #3              ; adjust for taps
+
+    ldr             r4, [sp, #36]           ; x_step_q4
+    ldr             r5, [sp, #32]           ; filter_x
+    cmp             r4, #16
+    bne             call_horiz_c_convolve   ; x_step_q4 != 16
+
+    ldr             r6, [sp, #48]           ; w
+    ldr             r7, [sp, #52]           ; h
+
+    vld1.s16        {q0}, [r5]              ; filter_x
+
+    add             r8, r1, r1, lsl #1      ; src_stride * 3
+    add             r8, r8, #4              ; src_stride * 3 + 4
+    rsb             r8, r8, #0              ; reset for src
+
+    add             r4, r3, r3, lsl #1      ; dst_stride * 3
+    sub             r4, r4, #4              ; dst_stride * 3 - 4
+    rsb             r4, r4, #0              ; reset for dst
+
+    sub             r9, r1, #8              ; post increment for src load
+
+    rsb             r1, r6, r1, lsl #2      ; reset src for outer loop
+    rsb             r12, r6, r3, lsl #2     ; reset dst for outer loop
+
+    mov             r10, r6                 ; w loop counter
+
+loop_horiz
+    vld4.u8         {d24[0], d25[0], d26[0], d27[0]}, [r0]!
+    vld4.u8         {d24[4], d25[4], d26[4], d27[4]}, [r0]!
+    vld3.u8         {d28[0], d29[0], d30[0]}, [r0], r9
+
+    vld4.u8         {d24[1], d25[1], d26[1], d27[1]}, [r0]!
+    vld4.u8         {d24[5], d25[5], d26[5], d27[5]}, [r0]!
+    vld3.u8         {d28[1], d29[1], d30[1]}, [r0], r9
+
+    vld4.u8         {d24[2], d25[2], d26[2], d27[2]}, [r0]!
+    vld4.u8         {d24[6], d25[6], d26[6], d27[6]}, [r0]!
+    vld3.u8         {d28[2], d29[2], d30[2]}, [r0], r9
+
+    vld4.u8         {d24[3], d25[3], d26[3], d27[3]}, [r0]!
+    vld4.u8         {d24[7], d25[7], d26[7], d27[7]}, [r0]!
+    vld3.u8         {d28[3], d29[3], d30[3]}, [r0], r8
+
+    ; extract to s16
+    vmovl.u8        q8, d24
+    vmovl.u8        q9, d25
+    vmovl.u8        q10, d26
+    vmovl.u8        q11, d27
+    vtrn.32         d28, d29 ; only the first half is populated
+    vmovl.u8        q12, d28
+    vmovl.u8        q13, d30
+
+    ; src[] * filter_x
+    MULTIPLY_BY_Q0 q1, d16, d18, d20, d22, d17, d19, d21, d23
+    MULTIPLY_BY_Q0 q2, d18, d20, d22, d17, d19, d21, d23, d24
+    MULTIPLY_BY_Q0 q14, d20, d22, d17, d19, d21, d23, d24, d25
+    MULTIPLY_BY_Q0 q15, d22, d17, d19, d21, d23, d24, d25, d26
+
+    ; += 64 >> 7
+    vqrshrun.s32    d2, q1, #7
+    vqrshrun.s32    d3, q2, #7
+    vqrshrun.s32    d4, q14, #7
+    vqrshrun.s32    d5, q15, #7
+
+    ; saturate
+    vqshrn.u16      d2, q1, #0
+    vqshrn.u16      d3, q2, #0
+
+    ; transpose
+    vtrn.16         d2, d3
+    vtrn.32         d2, d3
+    vtrn.8          d2, d3
+
+    vst1.u32        {d2[0]}, [r2], r3
+    vst1.u32        {d3[0]}, [r2], r3
+    vst1.u32        {d2[1]}, [r2], r3
+    vst1.u32        {d3[1]}, [r2], r4
+
+    subs            r6, r6, #4              ; w -= 4
+    bgt             loop_horiz
+
+    ; outer loop
+    mov             r6, r10                 ; restore w counter
+    add             r0, r0, r1              ; src += src_stride * 4 - w
+    add             r2, r2, r12             ; dst += dst_stride * 4 - w
+    subs            r7, r7, #4              ; h -= 4
+    bgt loop_horiz
+
+    pop             {r4-r10, pc}
+
+call_horiz_c_convolve
+    pop             {r4-r10, lr}
+    add             r0, r0, #3              ; un-adjust for taps
+    b               vp9_convolve8_horiz_c
+
+
+    ENDP
+
+|vp9_convolve8_vert_neon| PROC
+    push            {r4-r10, lr}
+
+    ; adjust for taps
+    sub             r0, r0, r1
+    sub             r0, r0, r1, lsl #1
+
+    ldr             r6, [sp, #44]           ; y_step_q4
+    ldr             r7, [sp, #40]           ; filter_y
+    cmp             r6, #16
+    bne             call_vert_c_convolve    ; y_step_q4 != 16
+
+    ldr             r8, [sp, #48]           ; w
+    ldr             r9, [sp, #52]           ; h
+
+    vld1.s16        {q0}, [r7]              ; filter_y
+
+    mov             r5, r1, lsl #1          ; src_stride * 2
+    add             r5, r5, r1, lsl #3      ; src_stride * 10
+    sub             r5, r5, #4              ; src_stride * 10 + 4
+    rsb             r5, r5, #0              ; reset for src
+
+    add             r6, r3, r3, lsl #1      ; dst_stride * 3
+    sub             r6, r6, #4              ; dst_stride * 3 - 4
+    rsb             r6, r6, #0              ; reset for dst
+
+    rsb             r7, r8, r1, lsl #2      ; reset src for outer loop
+    rsb             r12, r8, r3, lsl #2     ; reset dst for outer loop
+
+    mov             r10, r8                 ; w loop counter
+
+loop_vert
+    ; always process a 4x4 block at a time
+    vld1.u32        {d16[0]}, [r0], r1
+    vld1.u32        {d16[1]}, [r0], r1
+    vld1.u32        {d18[0]}, [r0], r1
+    vld1.u32        {d18[1]}, [r0], r1
+    vld1.u32        {d20[0]}, [r0], r1
+    vld1.u32        {d20[1]}, [r0], r1
+    vld1.u32        {d22[0]}, [r0], r1
+    vld1.u32        {d22[1]}, [r0], r1
+    vld1.u32        {d24[0]}, [r0], r1
+    vld1.u32        {d24[1]}, [r0], r1
+    vld1.u32        {d26[0]}, [r0], r5
+
+    ; extract to s16
+    vmovl.u8        q8, d16
+    vmovl.u8        q9, d18
+    vmovl.u8        q10, d20
+    vmovl.u8        q11, d22
+    vmovl.u8        q12, d24
+    vmovl.u8        q13, d26
+
+    ; src[] * filter_y
+    MULTIPLY_BY_Q0 q1, d16, d17, d18, d19, d20, d21, d22, d23
+    MULTIPLY_BY_Q0 q2, d17, d18, d19, d20, d21, d22, d23, d24
+    MULTIPLY_BY_Q0 q14, d18, d19, d20, d21, d22, d23, d24, d25
+    MULTIPLY_BY_Q0 q15, d19, d20, d21, d22, d23, d24, d25, d26
+
+    ; += 64 >> 7
+    vqrshrun.s32    d2, q1, #7
+    vqrshrun.s32    d3, q2, #7
+    vqrshrun.s32    d4, q14, #7
+    vqrshrun.s32    d5, q15, #7
+
+    ; saturate
+    vqshrn.u16      d2, q1, #0
+    vqshrn.u16      d3, q2, #0
+
+    vst1.u32        {d2[0]}, [r2], r3
+    vst1.u32        {d2[1]}, [r2], r3
+    vst1.u32        {d3[0]}, [r2], r3
+    vst1.u32        {d3[1]}, [r2], r6
+
+    subs            r8, r8, #4              ; w -= 4
+    bgt             loop_vert
+
+    ; outer loop
+    mov             r8, r10                 ; restore w counter
+    add             r0, r0, r7              ; src += 4 * src_stride - w
+    add             r2, r2, r12             ; dst += 4 * dst_stride - w
+    subs            r9, r9, #4              ; h -= 4
+    bgt             loop_vert
+
+    pop             {r4-r10, pc}
+
+call_vert_c_convolve
+    pop             {r4-r10, lr}
+    ; un-adjust for taps
+    add             r0, r0, r1
+    add             r0, r0, r1, lsl #1
+    b               vp9_convolve8_vert_c
+
+    ENDP
+    END
diff --git a/vp9/common/arm/neon/vp9_dc_only_idct_add_neon.asm b/vp9/common/arm/neon/vp9_dc_only_idct_add_neon.asm
new file mode 100644
index 0000000..60a0d98
--- /dev/null
+++ b/vp9/common/arm/neon/vp9_dc_only_idct_add_neon.asm
@@ -0,0 +1,69 @@
+;
+;  Copyright (c) 2013 The WebM project authors. All Rights Reserved.
+;
+;  Use of this source code is governed by a BSD-style license and patent
+;  grant that can be found in the LICENSE file in the root of the source
+;  tree. All contributing project authors may be found in the AUTHORS
+;  file in the root of the source tree.
+;
+
+
+    EXPORT  |vp9_dc_only_idct_add_neon|
+    ARM
+    REQUIRE8
+    PRESERVE8
+
+    AREA ||.text||, CODE, READONLY, ALIGN=2
+
+;void vp9_dc_only_idct_add_neon(int input_dc, uint8_t *pred_ptr,
+;                            uint8_t *dst_ptr, int pitch, int stride)
+;
+; r0  int input_dc
+; r1  uint8_t *pred_ptr
+; r2  uint8_t *dst_ptr
+; r3  int pitch
+; sp  int stride
+
+|vp9_dc_only_idct_add_neon| PROC
+
+    ; generate cospi_16_64 = 11585
+    mov              r12, #0x2d00
+    add              r12, #0x41
+
+    ; dct_const_round_shift(input_dc * cospi_16_64)
+    mul              r0, r0, r12               ; input_dc * cospi_16_64
+    add              r0, r0, #0x2000           ; +(1 << ((DCT_CONST_BITS) - 1))
+    asr              r0, r0, #14               ; >> DCT_CONST_BITS
+
+    ; dct_const_round_shift(out * cospi_16_64)
+    mul              r0, r0, r12               ; out * cospi_16_64
+    add              r0, r0, #0x2000           ; +(1 << ((DCT_CONST_BITS) - 1))
+    asr              r0, r0, #14               ; >> DCT_CONST_BITS
+
+    ; ROUND_POWER_OF_TWO(out, 4)
+    add              r0, r0, #8                ; + (1 <<((4) - 1))
+    asr              r0, r0, #4                ; >> 4
+
+    vdup.16         q0, r0;                   ; duplicate a1
+    ldr              r12, [sp]                 ; load stride
+
+    vld1.32         {d2[0]}, [r1], r3
+    vld1.32         {d2[1]}, [r1], r3
+    vld1.32         {d4[0]}, [r1], r3
+    vld1.32         {d4[1]}, [r1]
+
+    vaddw.u8        q1, q0, d2                ; a1 + pred_ptr[c]
+    vaddw.u8        q2, q0, d4
+
+    vqmovun.s16     d2, q1                    ; clip_pixel
+    vqmovun.s16     d4, q2
+
+    vst1.32         {d2[0]}, [r2], r12
+    vst1.32         {d2[1]}, [r2], r12
+    vst1.32         {d4[0]}, [r2], r12
+    vst1.32         {d4[1]}, [r2]
+
+    bx               lr
+    ENDP             ; |vp9_dc_only_idct_add_neon|
+
+    END
diff --git a/vp9/common/vp9_blockd.h b/vp9/common/vp9_blockd.h
index 385dcc1..e67250b 100644
--- a/vp9/common/vp9_blockd.h
+++ b/vp9/common/vp9_blockd.h
@@ -13,18 +13,19 @@
 #define VP9_COMMON_VP9_BLOCKD_H_
 
 #include "./vpx_config.h"
-#include "vpx_scale/yv12config.h"
-#include "vp9/common/vp9_convolve.h"
-#include "vp9/common/vp9_mv.h"
-#include "vp9/common/vp9_treecoder.h"
+
 #include "vpx_ports/mem.h"
+#include "vpx_scale/yv12config.h"
+
 #include "vp9/common/vp9_common.h"
-#include "vp9/common/vp9_enums.h"
 #include "vp9/common/vp9_common_data.h"
+#include "vp9/common/vp9_convolve.h"
+#include "vp9/common/vp9_enums.h"
+#include "vp9/common/vp9_mv.h"
+#include "vp9/common/vp9_seg_common.h"
+#include "vp9/common/vp9_treecoder.h"
 
 #define BLOCK_SIZE_GROUPS   4
-#define MAX_MB_SEGMENTS     8
-#define MB_SEG_TREE_PROBS   (MAX_MB_SEGMENTS-1)
 
 #define PREDICTION_PROBS 3
 
@@ -34,8 +35,6 @@
 #define MAX_MODE_LF_DELTAS      2
 
 /* Segment Feature Masks */
-#define SEGMENT_DELTADATA   0
-#define SEGMENT_ABSDATA     1
 #define MAX_MV_REF_CANDIDATES 2
 
 #define INTRA_INTER_CONTEXTS 4
@@ -94,15 +93,6 @@
 
 // Segment level features.
 typedef enum {
-  SEG_LVL_ALT_Q = 0,               // Use alternate Quantizer ....
-  SEG_LVL_ALT_LF = 1,              // Use alternate loop filter value...
-  SEG_LVL_REF_FRAME = 2,           // Optional Segment reference frame
-  SEG_LVL_SKIP = 3,                // Optional Segment (0,0) + skip mode
-  SEG_LVL_MAX = 4                  // Number of MB level features supported
-} SEG_LVL_FEATURES;
-
-// Segment level features.
-typedef enum {
   TX_4X4 = 0,                      // 4x4 dct transform
   TX_8X8 = 1,                      // 8x8 dct transform
   TX_16X16 = 2,                    // 16x16 dct transform
@@ -253,32 +243,12 @@
   int left_available;
   int right_available;
 
+  struct segmentation seg;
+
   // partition contexts
   PARTITION_CONTEXT *above_seg_context;
   PARTITION_CONTEXT *left_seg_context;
 
-  /* 0 (disable) 1 (enable) segmentation */
-  unsigned char segmentation_enabled;
-
-  /* 0 (do not update) 1 (update) the macroblock segmentation map. */
-  unsigned char update_mb_segmentation_map;
-
-  /* 0 (do not update) 1 (update) the macroblock segmentation feature data. */
-  unsigned char update_mb_segmentation_data;
-
-  /* 0 (do not update) 1 (update) the macroblock segmentation feature data. */
-  unsigned char mb_segment_abs_delta;
-
-  /* Per frame flags that define which MB level features (such as quantizer or loop filter level) */
-  /* are enabled and when enabled the proabilities used to decode the per MB flags in MB_MODE_INFO */
-
-  // Probability Tree used to code Segment number
-  vp9_prob mb_segment_tree_probs[MB_SEG_TREE_PROBS];
-
-  // Segment features
-  int16_t segment_feature_data[MAX_MB_SEGMENTS][SEG_LVL_MAX];
-  unsigned int segment_feature_mask[MAX_MB_SEGMENTS];
-
   /* mode_based Loop filter adjustment */
   unsigned char mode_ref_lf_delta_enabled;
   unsigned char mode_ref_lf_delta_update;
diff --git a/vp9/common/vp9_convolve.c b/vp9/common/vp9_convolve.c
index 914afa7..6f1e418 100644
--- a/vp9/common/vp9_convolve.c
+++ b/vp9/common/vp9_convolve.c
@@ -38,8 +38,8 @@
  */
  #define ALIGN_FILTERS_256 1
 
-static void convolve_horiz_c(const uint8_t *src, int src_stride,
-                             uint8_t *dst, int dst_stride,
+static void convolve_horiz_c(const uint8_t *src, ptrdiff_t src_stride,
+                             uint8_t *dst, ptrdiff_t dst_stride,
                              const int16_t *filter_x0, int x_step_q4,
                              const int16_t *filter_y, int y_step_q4,
                              int w, int h, int taps) {
@@ -80,8 +80,8 @@
   }
 }
 
-static void convolve_avg_horiz_c(const uint8_t *src, int src_stride,
-                                 uint8_t *dst, int dst_stride,
+static void convolve_avg_horiz_c(const uint8_t *src, ptrdiff_t src_stride,
+                                 uint8_t *dst, ptrdiff_t dst_stride,
                                  const int16_t *filter_x0, int x_step_q4,
                                  const int16_t *filter_y, int y_step_q4,
                                  int w, int h, int taps) {
@@ -122,8 +122,8 @@
   }
 }
 
-static void convolve_vert_c(const uint8_t *src, int src_stride,
-                            uint8_t *dst, int dst_stride,
+static void convolve_vert_c(const uint8_t *src, ptrdiff_t src_stride,
+                            uint8_t *dst, ptrdiff_t dst_stride,
                             const int16_t *filter_x, int x_step_q4,
                             const int16_t *filter_y0, int y_step_q4,
                             int w, int h, int taps) {
@@ -164,8 +164,8 @@
   }
 }
 
-static void convolve_avg_vert_c(const uint8_t *src, int src_stride,
-                                uint8_t *dst, int dst_stride,
+static void convolve_avg_vert_c(const uint8_t *src, ptrdiff_t src_stride,
+                                uint8_t *dst, ptrdiff_t dst_stride,
                                 const int16_t *filter_x, int x_step_q4,
                                 const int16_t *filter_y0, int y_step_q4,
                                 int w, int h, int taps) {
@@ -207,8 +207,8 @@
   }
 }
 
-static void convolve_c(const uint8_t *src, int src_stride,
-                       uint8_t *dst, int dst_stride,
+static void convolve_c(const uint8_t *src, ptrdiff_t src_stride,
+                       uint8_t *dst, ptrdiff_t dst_stride,
                        const int16_t *filter_x, int x_step_q4,
                        const int16_t *filter_y, int y_step_q4,
                        int w, int h, int taps) {
@@ -237,8 +237,8 @@
                   w, h, taps);
 }
 
-static void convolve_avg_c(const uint8_t *src, int src_stride,
-                           uint8_t *dst, int dst_stride,
+static void convolve_avg_c(const uint8_t *src, ptrdiff_t src_stride,
+                           uint8_t *dst, ptrdiff_t dst_stride,
                            const int16_t *filter_x, int x_step_q4,
                            const int16_t *filter_y, int y_step_q4,
                            int w, int h, int taps) {
@@ -267,8 +267,8 @@
                       w, h, taps);
 }
 
-void vp9_convolve8_horiz_c(const uint8_t *src, int src_stride,
-                           uint8_t *dst, int dst_stride,
+void vp9_convolve8_horiz_c(const uint8_t *src, ptrdiff_t src_stride,
+                           uint8_t *dst, ptrdiff_t dst_stride,
                            const int16_t *filter_x, int x_step_q4,
                            const int16_t *filter_y, int y_step_q4,
                            int w, int h) {
@@ -277,8 +277,8 @@
                    w, h, 8);
 }
 
-void vp9_convolve8_avg_horiz_c(const uint8_t *src, int src_stride,
-                               uint8_t *dst, int dst_stride,
+void vp9_convolve8_avg_horiz_c(const uint8_t *src, ptrdiff_t src_stride,
+                               uint8_t *dst, ptrdiff_t dst_stride,
                                const int16_t *filter_x, int x_step_q4,
                                const int16_t *filter_y, int y_step_q4,
                                int w, int h) {
@@ -287,8 +287,8 @@
                        w, h, 8);
 }
 
-void vp9_convolve8_vert_c(const uint8_t *src, int src_stride,
-                          uint8_t *dst, int dst_stride,
+void vp9_convolve8_vert_c(const uint8_t *src, ptrdiff_t src_stride,
+                          uint8_t *dst, ptrdiff_t dst_stride,
                           const int16_t *filter_x, int x_step_q4,
                           const int16_t *filter_y, int y_step_q4,
                           int w, int h) {
@@ -297,8 +297,8 @@
                   w, h, 8);
 }
 
-void vp9_convolve8_avg_vert_c(const uint8_t *src, int src_stride,
-                              uint8_t *dst, int dst_stride,
+void vp9_convolve8_avg_vert_c(const uint8_t *src, ptrdiff_t src_stride,
+                              uint8_t *dst, ptrdiff_t dst_stride,
                               const int16_t *filter_x, int x_step_q4,
                               const int16_t *filter_y, int y_step_q4,
                               int w, int h) {
@@ -307,8 +307,8 @@
                       w, h, 8);
 }
 
-void vp9_convolve8_c(const uint8_t *src, int src_stride,
-                     uint8_t *dst, int dst_stride,
+void vp9_convolve8_c(const uint8_t *src, ptrdiff_t src_stride,
+                     uint8_t *dst, ptrdiff_t dst_stride,
                      const int16_t *filter_x, int x_step_q4,
                      const int16_t *filter_y, int y_step_q4,
                      int w, int h) {
@@ -317,8 +317,8 @@
              w, h, 8);
 }
 
-void vp9_convolve8_avg_c(const uint8_t *src, int src_stride,
-                         uint8_t *dst, int dst_stride,
+void vp9_convolve8_avg_c(const uint8_t *src, ptrdiff_t src_stride,
+                         uint8_t *dst, ptrdiff_t dst_stride,
                          const int16_t *filter_x, int x_step_q4,
                          const int16_t *filter_y, int y_step_q4,
                          int w, int h) {
@@ -339,33 +339,25 @@
                    w, h);
 }
 
-void vp9_convolve_copy(const uint8_t *src, int src_stride,
-                       uint8_t *dst, int dst_stride,
-                       const int16_t *filter_x, int filter_x_stride,
-                       const int16_t *filter_y, int filter_y_stride,
-                       int w, int h) {
-  if (w == 16 && h == 16) {
-    vp9_copy_mem16x16(src, src_stride, dst, dst_stride);
-  } else if (w == 8 && h == 8) {
-    vp9_copy_mem8x8(src, src_stride, dst, dst_stride);
-  } else if (w == 8 && h == 4) {
-    vp9_copy_mem8x4(src, src_stride, dst, dst_stride);
-  } else {
-    int r;
+void vp9_convolve_copy_c(const uint8_t *src, ptrdiff_t src_stride,
+                         uint8_t *dst, ptrdiff_t dst_stride,
+                         const int16_t *filter_x, int filter_x_stride,
+                         const int16_t *filter_y, int filter_y_stride,
+                         int w, int h) {
+  int r;
 
-    for (r = h; r > 0; --r) {
-      memcpy(dst, src, w);
-      src += src_stride;
-      dst += dst_stride;
-    }
+  for (r = h; r > 0; --r) {
+    memcpy(dst, src, w);
+    src += src_stride;
+    dst += dst_stride;
   }
 }
 
-void vp9_convolve_avg(const uint8_t *src, int src_stride,
-                      uint8_t *dst, int dst_stride,
-                      const int16_t *filter_x, int filter_x_stride,
-                      const int16_t *filter_y, int filter_y_stride,
-                      int w, int h) {
+void vp9_convolve_avg_c(const uint8_t *src, ptrdiff_t src_stride,
+                        uint8_t *dst, ptrdiff_t dst_stride,
+                        const int16_t *filter_x, int filter_x_stride,
+                        const int16_t *filter_y, int filter_y_stride,
+                        int w, int h) {
   int x, y;
 
   for (y = 0; y < h; ++y) {
diff --git a/vp9/common/vp9_convolve.h b/vp9/common/vp9_convolve.h
index 0596080..3de8111 100644
--- a/vp9/common/vp9_convolve.h
+++ b/vp9/common/vp9_convolve.h
@@ -13,26 +13,12 @@
 #include "./vpx_config.h"
 #include "vpx/vpx_integer.h"
 
-typedef void (*convolve_fn_t)(const uint8_t *src, int src_stride,
-                              uint8_t *dst, int dst_stride,
+typedef void (*convolve_fn_t)(const uint8_t *src, ptrdiff_t src_stride,
+                              uint8_t *dst, ptrdiff_t dst_stride,
                               const int16_t *filter_x, int x_step_q4,
                               const int16_t *filter_y, int y_step_q4,
                               int w, int h);
 
-// Not a convolution, a block copy conforming to the convolution prototype
-void vp9_convolve_copy(const uint8_t *src, int src_stride,
-                       uint8_t *dst, int dst_stride,
-                       const int16_t *filter_x, int x_step_q4,
-                       const int16_t *filter_y, int y_step_q4,
-                       int w, int h);
-
-// Not a convolution, a block average conforming to the convolution prototype
-void vp9_convolve_avg(const uint8_t *src, int src_stride,
-                      uint8_t *dst, int dst_stride,
-                      const int16_t *filter_x, int x_step_q4,
-                      const int16_t *filter_y, int y_step_q4,
-                      int w, int h);
-
 struct subpix_fn_table {
   const int16_t (*filter_x)[8];
   const int16_t (*filter_y)[8];
diff --git a/vp9/common/vp9_entropymode.c b/vp9/common/vp9_entropymode.c
index 1cdf138..0b5f2ea 100644
--- a/vp9/common/vp9_entropymode.c
+++ b/vp9/common/vp9_entropymode.c
@@ -460,8 +460,8 @@
   // Reset the segment feature data to the default stats:
   // Features disabled, 0, with delta coding (Default state).
   int i;
-  vp9_clearall_segfeatures(xd);
-  xd->mb_segment_abs_delta = SEGMENT_DELTADATA;
+  vp9_clearall_segfeatures(&xd->seg);
+  xd->seg.abs_delta = SEGMENT_DELTADATA;
   if (cm->last_frame_seg_map)
     vpx_memset(cm->last_frame_seg_map, 0, (cm->mi_rows * cm->mi_cols));
 
diff --git a/vp9/common/vp9_entropymv.c b/vp9/common/vp9_entropymv.c
index 50e8463..ed6af66 100644
--- a/vp9/common/vp9_entropymv.c
+++ b/vp9/common/vp9_entropymv.c
@@ -56,7 +56,7 @@
 };
 struct vp9_token vp9_mv_fp_encodings[4];
 
-const nmv_context vp9_default_nmv_context = {
+static const nmv_context default_nmv_context = {
   {32, 64, 96},
   {
     { /* vert component */
@@ -360,5 +360,5 @@
 }
 
 void vp9_init_mv_probs(VP9_COMMON *cm) {
-  vpx_memcpy(&cm->fc.nmvc, &vp9_default_nmv_context, sizeof(nmv_context));
+  cm->fc.nmvc = default_nmv_context;
 }
diff --git a/vp9/common/vp9_entropymv.h b/vp9/common/vp9_entropymv.h
index 15f9ada..0df92d0 100644
--- a/vp9/common/vp9_entropymv.h
+++ b/vp9/common/vp9_entropymv.h
@@ -130,7 +130,6 @@
 
 void vp9_inc_mv(const MV *mv, const MV *ref, nmv_context_counts *mvctx,
                 int usehp);
-extern const nmv_context vp9_default_nmv_context;
 
 void vp9_counts_process(nmv_context_counts *NMVcount, int usehp);
 
diff --git a/vp9/common/vp9_loopfilter.c b/vp9/common/vp9_loopfilter.c
index 9d2e2ea..37209a7 100644
--- a/vp9/common/vp9_loopfilter.c
+++ b/vp9/common/vp9_loopfilter.c
@@ -92,9 +92,9 @@
     int lvl_seg = default_filt_lvl, ref, mode, intra_lvl;
 
     // Set the baseline filter values for each segment
-    if (vp9_segfeature_active(xd, seg, SEG_LVL_ALT_LF)) {
-      const int data = vp9_get_segdata(xd, seg, SEG_LVL_ALT_LF);
-      lvl_seg = xd->mb_segment_abs_delta == SEGMENT_ABSDATA
+    if (vp9_segfeature_active(&xd->seg, seg, SEG_LVL_ALT_LF)) {
+      const int data = vp9_get_segdata(&xd->seg, seg, SEG_LVL_ALT_LF);
+      lvl_seg = xd->seg.abs_delta == SEGMENT_ABSDATA
                   ? data
                   : clamp(default_filt_lvl + data, 0, MAX_LOOP_FILTER);
     }
@@ -186,14 +186,22 @@
                                      int only_4x4_1,
                                      const struct loop_filter_info *lfi) {
   unsigned int mask;
+  int count;
 
   for (mask = mask_16x16 | mask_8x8 | mask_4x4 | mask_4x4_int;
-       mask; mask >>= 1) {
+       mask; mask >>= count) {
+    count =1;
     if (mask & 1) {
       if (!only_4x4_1) {
         if (mask_16x16 & 1) {
-          vp9_mb_lpf_horizontal_edge_w(s, pitch, lfi->mblim, lfi->lim,
-                                       lfi->hev_thr);
+          if ((mask_16x16 & 3) == 3) {
+            vp9_mb_lpf_horizontal_edge_w(s, pitch, lfi->mblim, lfi->lim,
+                                         lfi->hev_thr, 2);
+            count = 2;
+          } else {
+            vp9_mb_lpf_horizontal_edge_w(s, pitch, lfi->mblim, lfi->lim,
+                                         lfi->hev_thr, 1);
+          }
           assert(!(mask_8x8 & 1));
           assert(!(mask_4x4 & 1));
           assert(!(mask_4x4_int & 1));
@@ -214,12 +222,12 @@
         vp9_loop_filter_horizontal_edge(s + 4 * pitch, pitch, lfi->mblim,
                                         lfi->lim, lfi->hev_thr, 1);
     }
-    s += 8;
-    lfi++;
-    mask_16x16 >>= 1;
-    mask_8x8 >>= 1;
-    mask_4x4 >>= 1;
-    mask_4x4_int >>= 1;
+    s += 8 * count;
+    lfi += count;
+    mask_16x16 >>= count;
+    mask_8x8 >>= count;
+    mask_4x4 >>= count;
+    mask_4x4_int >>= count;
   }
 }
 
diff --git a/vp9/common/vp9_loopfilter.h b/vp9/common/vp9_loopfilter.h
index 2582979..52d3b2d 100644
--- a/vp9/common/vp9_loopfilter.h
+++ b/vp9/common/vp9_loopfilter.h
@@ -13,7 +13,9 @@
 
 #include "vpx_ports/mem.h"
 #include "vpx_config.h"
+
 #include "vp9/common/vp9_blockd.h"
+#include "vp9/common/vp9_seg_common.h"
 
 #define MAX_LOOP_FILTER 63
 #define MAX_SHARPNESS 7
diff --git a/vp9/common/vp9_loopfilter_filters.c b/vp9/common/vp9_loopfilter_filters.c
index 0efbcaf..a0359d2 100644
--- a/vp9/common/vp9_loopfilter_filters.c
+++ b/vp9/common/vp9_loopfilter_filters.c
@@ -258,12 +258,13 @@
 void vp9_mb_lpf_horizontal_edge_w_c(uint8_t *s, int p,
                                     const uint8_t *blimit,
                                     const uint8_t *limit,
-                                    const uint8_t *thresh) {
+                                    const uint8_t *thresh,
+                                    int count) {
   int i;
 
   // loop filter designed to work using chars so that we can make maximum use
   // of 8 bit simd instructions.
-  for (i = 0; i < 8; ++i) {
+  for (i = 0; i < 8 * count; ++i) {
     const uint8_t p3 = s[-4 * p], p2 = s[-3 * p], p1 = s[-2 * p], p0 = s[-p];
     const uint8_t q0 = s[0 * p], q1 = s[1 * p], q2 = s[2 * p], q3 = s[3 * p];
     const int8_t mask = filter_mask(*limit, *blimit,
diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h
index 7094e71..b7025ca 100644
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -247,10 +247,6 @@
                          [VP9_INTRA_MODES - 1];
   vp9_prob kf_uv_mode_prob[VP9_INTRA_MODES] [VP9_INTRA_MODES - 1];
 
-  // Context probabilities when using predictive coding of segment id
-  vp9_prob segment_pred_probs[PREDICTION_PROBS];
-  unsigned char temporal_update;
-
   // Context probabilities for reference frame prediction
   int allow_comp_inter_inter;
   MV_REFERENCE_FRAME comp_fixed_ref;
diff --git a/vp9/common/vp9_pred_common.h b/vp9/common/vp9_pred_common.h
index 3ec1ff7..21a7d80 100644
--- a/vp9/common/vp9_pred_common.h
+++ b/vp9/common/vp9_pred_common.h
@@ -32,7 +32,7 @@
 static INLINE vp9_prob vp9_get_pred_prob_seg_id(const VP9_COMMON *cm,
                                                 const MACROBLOCKD *xd) {
   const int pred_context = vp9_get_pred_context_seg_id(cm, xd);
-  return cm->segment_pred_probs[pred_context];
+  return xd->seg.pred_probs[pred_context];
 }
 static INLINE unsigned char vp9_get_pred_flag_seg_id(
     const MACROBLOCKD * const xd) {
diff --git a/vp9/common/vp9_quant_common.c b/vp9/common/vp9_quant_common.c
index 295c8e7..2b81c2e 100644
--- a/vp9/common/vp9_quant_common.c
+++ b/vp9/common/vp9_quant_common.c
@@ -57,9 +57,9 @@
 
 
 int vp9_get_qindex(MACROBLOCKD *xd, int segment_id, int base_qindex) {
-  if (vp9_segfeature_active(xd, segment_id, SEG_LVL_ALT_Q)) {
-    const int data = vp9_get_segdata(xd, segment_id, SEG_LVL_ALT_Q);
-    return xd->mb_segment_abs_delta == SEGMENT_ABSDATA ?
+  if (vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_ALT_Q)) {
+    const int data = vp9_get_segdata(&xd->seg, segment_id, SEG_LVL_ALT_Q);
+    return xd->seg.abs_delta == SEGMENT_ABSDATA ?
                data :  // Abs value
                clamp(base_qindex + data, 0, MAXQ);  // Delta value
   } else {
diff --git a/vp9/common/vp9_reconinter.c b/vp9/common/vp9_reconinter.c
index 265a19a..c29fd14 100644
--- a/vp9/common/vp9_reconinter.c
+++ b/vp9/common/vp9_reconinter.c
@@ -194,93 +194,6 @@
   assert(((intptr_t)xd->subpix.filter_x & 0xff) == 0);
 }
 
-void vp9_copy_mem16x16_c(const uint8_t *src,
-                         int src_stride,
-                         uint8_t *dst,
-                         int dst_stride) {
-  int r;
-
-  for (r = 0; r < 16; r++) {
-#if !(CONFIG_FAST_UNALIGNED)
-    dst[0] = src[0];
-    dst[1] = src[1];
-    dst[2] = src[2];
-    dst[3] = src[3];
-    dst[4] = src[4];
-    dst[5] = src[5];
-    dst[6] = src[6];
-    dst[7] = src[7];
-    dst[8] = src[8];
-    dst[9] = src[9];
-    dst[10] = src[10];
-    dst[11] = src[11];
-    dst[12] = src[12];
-    dst[13] = src[13];
-    dst[14] = src[14];
-    dst[15] = src[15];
-
-#else
-    ((uint32_t *)dst)[0] = ((const uint32_t *)src)[0];
-    ((uint32_t *)dst)[1] = ((const uint32_t *)src)[1];
-    ((uint32_t *)dst)[2] = ((const uint32_t *)src)[2];
-    ((uint32_t *)dst)[3] = ((const uint32_t *)src)[3];
-
-#endif
-    src += src_stride;
-    dst += dst_stride;
-  }
-}
-
-void vp9_copy_mem8x8_c(const uint8_t *src,
-                       int src_stride,
-                       uint8_t *dst,
-                       int dst_stride) {
-  int r;
-
-  for (r = 0; r < 8; r++) {
-#if !(CONFIG_FAST_UNALIGNED)
-    dst[0] = src[0];
-    dst[1] = src[1];
-    dst[2] = src[2];
-    dst[3] = src[3];
-    dst[4] = src[4];
-    dst[5] = src[5];
-    dst[6] = src[6];
-    dst[7] = src[7];
-#else
-    ((uint32_t *)dst)[0] = ((const uint32_t *)src)[0];
-    ((uint32_t *)dst)[1] = ((const uint32_t *)src)[1];
-#endif
-    src += src_stride;
-    dst += dst_stride;
-  }
-}
-
-void vp9_copy_mem8x4_c(const uint8_t *src,
-                       int src_stride,
-                       uint8_t *dst,
-                       int dst_stride) {
-  int r;
-
-  for (r = 0; r < 4; r++) {
-#if !(CONFIG_FAST_UNALIGNED)
-    dst[0] = src[0];
-    dst[1] = src[1];
-    dst[2] = src[2];
-    dst[3] = src[3];
-    dst[4] = src[4];
-    dst[5] = src[5];
-    dst[6] = src[6];
-    dst[7] = src[7];
-#else
-    ((uint32_t *)dst)[0] = ((const uint32_t *)src)[0];
-    ((uint32_t *)dst)[1] = ((const uint32_t *)src)[1];
-#endif
-    src += src_stride;
-    dst += dst_stride;
-  }
-}
-
 void vp9_build_inter_predictor(const uint8_t *src, int src_stride,
                                uint8_t *dst, int dst_stride,
                                const int_mv *src_mv,
diff --git a/vp9/common/vp9_rtcd_defs.sh b/vp9/common/vp9_rtcd_defs.sh
index d861a7a..95cf3ac 100644
--- a/vp9/common/vp9_rtcd_defs.sh
+++ b/vp9/common/vp9_rtcd_defs.sh
@@ -43,17 +43,6 @@
 #
 # RECON
 #
-prototype void vp9_copy_mem16x16 "const uint8_t *src, int src_pitch, uint8_t *dst, int dst_pitch"
-specialize vp9_copy_mem16x16 mmx sse2 dspr2
-vp9_copy_mem16x16_dspr2=vp9_copy_mem16x16_dspr2
-
-prototype void vp9_copy_mem8x8 "const uint8_t *src, int src_pitch, uint8_t *dst, int dst_pitch"
-specialize vp9_copy_mem8x8 mmx dspr2
-vp9_copy_mem8x8_dspr2=vp9_copy_mem8x8_dspr2
-
-prototype void vp9_copy_mem8x4 "const uint8_t *src, int src_pitch, uint8_t *dst, int dst_pitch"
-specialize vp9_copy_mem8x4 mmx
-
 prototype void vp9_d27_predictor_4x4 "uint8_t *ypred_ptr, ptrdiff_t y_stride, uint8_t *yabove_row, uint8_t *yleft_col"
 specialize vp9_d27_predictor_4x4
 
@@ -233,7 +222,7 @@
 prototype void vp9_loop_filter_vertical_edge "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count"
 specialize vp9_loop_filter_vertical_edge mmx neon
 
-prototype void vp9_mb_lpf_horizontal_edge_w "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh"
+prototype void vp9_mb_lpf_horizontal_edge_w "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count"
 specialize vp9_mb_lpf_horizontal_edge_w sse2
 
 prototype void vp9_mbloop_filter_horizontal_edge "uint8_t *s, int pitch, const uint8_t *blimit, const uint8_t *limit, const uint8_t *thresh, int count"
@@ -275,22 +264,28 @@
 #
 # Sub Pixel Filters
 #
-prototype void vp9_convolve8 "const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h"
+prototype void vp9_convolve_copy "const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h"
+specialize vp9_convolve_copy sse2
+
+prototype void vp9_convolve_avg "const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h"
+specialize vp9_convolve_avg sse2
+
+prototype void vp9_convolve8 "const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h"
 specialize vp9_convolve8 ssse3
 
-prototype void vp9_convolve8_horiz "const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h"
-specialize vp9_convolve8_horiz ssse3
+prototype void vp9_convolve8_horiz "const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h"
+specialize vp9_convolve8_horiz ssse3 neon
 
-prototype void vp9_convolve8_vert "const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h"
-specialize vp9_convolve8_vert ssse3
+prototype void vp9_convolve8_vert "const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h"
+specialize vp9_convolve8_vert ssse3 neon
 
-prototype void vp9_convolve8_avg "const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h"
+prototype void vp9_convolve8_avg "const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h"
 specialize vp9_convolve8_avg ssse3
 
-prototype void vp9_convolve8_avg_horiz "const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h"
+prototype void vp9_convolve8_avg_horiz "const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h"
 specialize vp9_convolve8_avg_horiz ssse3
 
-prototype void vp9_convolve8_avg_vert "const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h"
+prototype void vp9_convolve8_avg_vert "const uint8_t *src, ptrdiff_t src_stride, uint8_t *dst, ptrdiff_t dst_stride, const int16_t *filter_x, int x_step_q4, const int16_t *filter_y, int y_step_q4, int w, int h"
 specialize vp9_convolve8_avg_vert ssse3
 
 #
@@ -330,7 +325,7 @@
 specialize vp9_short_idct10_32x32_add
 
 prototype void vp9_short_iht4x4_add "int16_t *input, uint8_t *dest, int dest_stride, int tx_type"
-specialize vp9_short_iht4x4_add
+specialize vp9_short_iht4x4_add sse2
 
 prototype void vp9_short_iht8x8_add "int16_t *input, uint8_t *dest, int dest_stride, int tx_type"
 specialize vp9_short_iht8x8_add
@@ -343,7 +338,7 @@
 # dct and add
 
 prototype void vp9_dc_only_idct_add "int input_dc, uint8_t *pred_ptr, uint8_t *dst_ptr, int pitch, int stride"
-specialize vp9_dc_only_idct_add sse2
+specialize vp9_dc_only_idct_add sse2 neon
 
 prototype void vp9_short_iwalsh4x4_1_add "int16_t *input, uint8_t *dest, int dest_stride"
 specialize vp9_short_iwalsh4x4_1_add
diff --git a/vp9/common/vp9_seg_common.c b/vp9/common/vp9_seg_common.c
index 9bf2072..9b13b5b 100644
--- a/vp9/common/vp9_seg_common.c
+++ b/vp9/common/vp9_seg_common.c
@@ -9,8 +9,11 @@
  */
 
 #include <assert.h>
+
 #include "vp9/common/vp9_blockd.h"
+#include "vp9/common/vp9_loopfilter.h"
 #include "vp9/common/vp9_seg_common.h"
+#include "vp9/common/vp9_quant_common.h"
 
 static const int seg_feature_data_signed[SEG_LVL_MAX] = { 1, 1, 0, 0 };
 
@@ -22,25 +25,25 @@
 // the coding mechanism is still subject to change so these provide a
 // convenient single point of change.
 
-int vp9_segfeature_active(const MACROBLOCKD *xd, int segment_id,
+int vp9_segfeature_active(const struct segmentation *seg, int segment_id,
                           SEG_LVL_FEATURES feature_id) {
-  return xd->segmentation_enabled &&
-         (xd->segment_feature_mask[segment_id] & (1 << feature_id));
+  return seg->enabled &&
+         (seg->feature_mask[segment_id] & (1 << feature_id));
 }
 
-void vp9_clearall_segfeatures(MACROBLOCKD *xd) {
-  vpx_memset(xd->segment_feature_data, 0, sizeof(xd->segment_feature_data));
-  vpx_memset(xd->segment_feature_mask, 0, sizeof(xd->segment_feature_mask));
+void vp9_clearall_segfeatures(struct segmentation *seg) {
+  vpx_memset(seg->feature_data, 0, sizeof(seg->feature_data));
+  vpx_memset(seg->feature_mask, 0, sizeof(seg->feature_mask));
 }
 
-void vp9_enable_segfeature(MACROBLOCKD *xd, int segment_id,
+void vp9_enable_segfeature(struct segmentation *seg, int segment_id,
                            SEG_LVL_FEATURES feature_id) {
-  xd->segment_feature_mask[segment_id] |= 1 << feature_id;
+  seg->feature_mask[segment_id] |= 1 << feature_id;
 }
 
-void vp9_disable_segfeature(MACROBLOCKD *xd, int segment_id,
+void vp9_disable_segfeature(struct segmentation *seg, int segment_id,
                             SEG_LVL_FEATURES feature_id) {
-  xd->segment_feature_mask[segment_id] &= ~(1 << feature_id);
+  seg->feature_mask[segment_id] &= ~(1 << feature_id);
 }
 
 int vp9_seg_feature_data_max(SEG_LVL_FEATURES feature_id) {
@@ -51,12 +54,12 @@
   return seg_feature_data_signed[feature_id];
 }
 
-void vp9_clear_segdata(MACROBLOCKD *xd, int segment_id,
+void vp9_clear_segdata(struct segmentation *seg, int segment_id,
                        SEG_LVL_FEATURES feature_id) {
-  xd->segment_feature_data[segment_id][feature_id] = 0;
+  seg->feature_data[segment_id][feature_id] = 0;
 }
 
-void vp9_set_segdata(MACROBLOCKD *xd, int segment_id,
+void vp9_set_segdata(struct segmentation *seg, int segment_id,
                      SEG_LVL_FEATURES feature_id, int seg_data) {
   assert(seg_data <= seg_feature_data_max[feature_id]);
   if (seg_data < 0) {
@@ -64,12 +67,12 @@
     assert(-seg_data <= seg_feature_data_max[feature_id]);
   }
 
-  xd->segment_feature_data[segment_id][feature_id] = seg_data;
+  seg->feature_data[segment_id][feature_id] = seg_data;
 }
 
-int vp9_get_segdata(const MACROBLOCKD *xd, int segment_id,
+int vp9_get_segdata(const struct segmentation *seg, int segment_id,
                     SEG_LVL_FEATURES feature_id) {
-  return xd->segment_feature_data[segment_id][feature_id];
+  return seg->feature_data[segment_id][feature_id];
 }
 
 
diff --git a/vp9/common/vp9_seg_common.h b/vp9/common/vp9_seg_common.h
index 74ba03c..f072a51 100644
--- a/vp9/common/vp9_seg_common.h
+++ b/vp9/common/vp9_seg_common.h
@@ -8,23 +8,54 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#include "vp9/common/vp9_onyxc_int.h"
-#include "vp9/common/vp9_blockd.h"
-
 #ifndef VP9_COMMON_VP9_SEG_COMMON_H_
 #define VP9_COMMON_VP9_SEG_COMMON_H_
 
-int vp9_segfeature_active(const MACROBLOCKD *xd,
+#include "vp9/common/vp9_treecoder.h"
+
+#define SEGMENT_DELTADATA   0
+#define SEGMENT_ABSDATA     1
+
+#define MAX_MB_SEGMENTS     8
+#define MB_SEG_TREE_PROBS   (MAX_MB_SEGMENTS-1)
+
+#define PREDICTION_PROBS 3
+
+// Segment level features.
+typedef enum {
+  SEG_LVL_ALT_Q = 0,               // Use alternate Quantizer ....
+  SEG_LVL_ALT_LF = 1,              // Use alternate loop filter value...
+  SEG_LVL_REF_FRAME = 2,           // Optional Segment reference frame
+  SEG_LVL_SKIP = 3,                // Optional Segment (0,0) + skip mode
+  SEG_LVL_MAX = 4                  // Number of MB level features supported
+} SEG_LVL_FEATURES;
+
+
+struct segmentation {
+  uint8_t enabled;
+  uint8_t update_map;
+  uint8_t update_data;
+  uint8_t abs_delta;
+  uint8_t temporal_update;
+
+  vp9_prob tree_probs[MB_SEG_TREE_PROBS];
+  vp9_prob pred_probs[PREDICTION_PROBS];
+
+  int16_t feature_data[MAX_MB_SEGMENTS][SEG_LVL_MAX];
+  unsigned int feature_mask[MAX_MB_SEGMENTS];
+};
+
+int vp9_segfeature_active(const struct segmentation *seg,
                           int segment_id,
                           SEG_LVL_FEATURES feature_id);
 
-void vp9_clearall_segfeatures(MACROBLOCKD *xd);
+void vp9_clearall_segfeatures(struct segmentation *seg);
 
-void vp9_enable_segfeature(MACROBLOCKD *xd,
+void vp9_enable_segfeature(struct segmentation *seg,
                            int segment_id,
                            SEG_LVL_FEATURES feature_id);
 
-void vp9_disable_segfeature(MACROBLOCKD *xd,
+void vp9_disable_segfeature(struct segmentation *seg,
                             int segment_id,
                             SEG_LVL_FEATURES feature_id);
 
@@ -32,16 +63,16 @@
 
 int vp9_is_segfeature_signed(SEG_LVL_FEATURES feature_id);
 
-void vp9_clear_segdata(MACROBLOCKD *xd,
+void vp9_clear_segdata(struct segmentation *seg,
                        int segment_id,
                        SEG_LVL_FEATURES feature_id);
 
-void vp9_set_segdata(MACROBLOCKD *xd,
+void vp9_set_segdata(struct segmentation *seg,
                      int segment_id,
                      SEG_LVL_FEATURES feature_id,
                      int seg_data);
 
-int vp9_get_segdata(const MACROBLOCKD *xd,
+int vp9_get_segdata(const struct segmentation *seg,
                     int segment_id,
                     SEG_LVL_FEATURES feature_id);
 
diff --git a/vp9/common/x86/vp9_asm_stubs.c b/vp9/common/x86/vp9_asm_stubs.c
index 2b66834..3f1c198 100644
--- a/vp9/common/x86/vp9_asm_stubs.c
+++ b/vp9/common/x86/vp9_asm_stubs.c
@@ -121,11 +121,12 @@
                                      unsigned int output_height,
                                      const short *filter);
 
-void vp9_convolve8_horiz_ssse3(const uint8_t *src, int src_stride,
-                               uint8_t *dst, int dst_stride,
+void vp9_convolve8_horiz_ssse3(const uint8_t *src, ptrdiff_t src_stride,
+                               uint8_t *dst, ptrdiff_t dst_stride,
                                const int16_t *filter_x, int x_step_q4,
                                const int16_t *filter_y, int y_step_q4,
                                int w, int h) {
+  /* Ensure the filter can be compressed to int16_t. */
   if (x_step_q4 == 16 && filter_x[3] != 128) {
     while (w >= 16) {
       vp9_filter_block1d16_h8_ssse3(src, src_stride,
@@ -159,8 +160,8 @@
   }
 }
 
-void vp9_convolve8_vert_ssse3(const uint8_t *src, int src_stride,
-                              uint8_t *dst, int dst_stride,
+void vp9_convolve8_vert_ssse3(const uint8_t *src, ptrdiff_t src_stride,
+                              uint8_t *dst, ptrdiff_t dst_stride,
                               const int16_t *filter_x, int x_step_q4,
                               const int16_t *filter_y, int y_step_q4,
                               int w, int h) {
@@ -197,8 +198,8 @@
   }
 }
 
-void vp9_convolve8_avg_horiz_ssse3(const uint8_t *src, int src_stride,
-                               uint8_t *dst, int dst_stride,
+void vp9_convolve8_avg_horiz_ssse3(const uint8_t *src, ptrdiff_t src_stride,
+                               uint8_t *dst, ptrdiff_t dst_stride,
                                const int16_t *filter_x, int x_step_q4,
                                const int16_t *filter_y, int y_step_q4,
                                int w, int h) {
@@ -235,8 +236,8 @@
   }
 }
 
-void vp9_convolve8_avg_vert_ssse3(const uint8_t *src, int src_stride,
-                              uint8_t *dst, int dst_stride,
+void vp9_convolve8_avg_vert_ssse3(const uint8_t *src, ptrdiff_t src_stride,
+                              uint8_t *dst, ptrdiff_t dst_stride,
                               const int16_t *filter_x, int x_step_q4,
                               const int16_t *filter_y, int y_step_q4,
                               int w, int h) {
@@ -273,8 +274,8 @@
   }
 }
 
-void vp9_convolve8_ssse3(const uint8_t *src, int src_stride,
-                         uint8_t *dst, int dst_stride,
+void vp9_convolve8_ssse3(const uint8_t *src, ptrdiff_t src_stride,
+                         uint8_t *dst, ptrdiff_t dst_stride,
                          const int16_t *filter_x, int x_step_q4,
                          const int16_t *filter_y, int y_step_q4,
                          int w, int h) {
@@ -294,8 +295,8 @@
   }
 }
 
-void vp9_convolve8_avg_ssse3(const uint8_t *src, int src_stride,
-                         uint8_t *dst, int dst_stride,
+void vp9_convolve8_avg_ssse3(const uint8_t *src, ptrdiff_t src_stride,
+                         uint8_t *dst, ptrdiff_t dst_stride,
                          const int16_t *filter_x, int x_step_q4,
                          const int16_t *filter_y, int y_step_q4,
                          int w, int h) {
diff --git a/vp9/common/x86/vp9_copy_sse2.asm b/vp9/common/x86/vp9_copy_sse2.asm
new file mode 100644
index 0000000..dd522c6
--- /dev/null
+++ b/vp9/common/x86/vp9_copy_sse2.asm
@@ -0,0 +1,152 @@
+;
+;  Copyright (c) 2010 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 "third_party/x86inc/x86inc.asm"
+
+SECTION .text
+
+%macro convolve_fn 1
+INIT_XMM sse2
+cglobal convolve_%1, 4, 7, 4, src, src_stride, dst, dst_stride, \
+                              fx, fxs, fy, fys, w, h
+  mov r4d, dword wm
+  cmp r4d, 4
+  je .w4
+  cmp r4d, 8
+  je .w8
+  cmp r4d, 16
+  je .w16
+  cmp r4d, 32
+  je .w32
+
+  mov                    r4d, dword hm
+.loop64:
+  movu                    m0, [srcq]
+  movu                    m1, [srcq+16]
+  movu                    m2, [srcq+32]
+  movu                    m3, [srcq+48]
+  add                   srcq, src_strideq
+%ifidn %1, avg
+  pavgb                   m0, [dstq]
+  pavgb                   m1, [dstq+16]
+  pavgb                   m2, [dstq+32]
+  pavgb                   m3, [dstq+48]
+%endif
+  mova             [dstq   ], m0
+  mova             [dstq+16], m1
+  mova             [dstq+32], m2
+  mova             [dstq+48], m3
+  add                   dstq, dst_strideq
+  dec                    r4d
+  jnz .loop64
+  RET
+
+.w32:
+  mov                    r4d, dword hm
+.loop32:
+  movu                    m0, [srcq]
+  movu                    m1, [srcq+16]
+  movu                    m2, [srcq+src_strideq]
+  movu                    m3, [srcq+src_strideq+16]
+  lea                   srcq, [srcq+src_strideq*2]
+%ifidn %1, avg
+  pavgb                   m0, [dstq]
+  pavgb                   m1, [dstq            +16]
+  pavgb                   m2, [dstq+dst_strideq]
+  pavgb                   m3, [dstq+dst_strideq+16]
+%endif
+  mova [dstq               ], m0
+  mova [dstq            +16], m1
+  mova [dstq+dst_strideq   ], m2
+  mova [dstq+dst_strideq+16], m3
+  lea                   dstq, [dstq+dst_strideq*2]
+  sub                    r4d, 2
+  jnz .loop32
+  RET
+
+.w16:
+  mov                    r4d, dword hm
+  lea                    r5q, [src_strideq*3]
+  lea                    r6q, [dst_strideq*3]
+.loop16:
+  movu                    m0, [srcq]
+  movu                    m1, [srcq+src_strideq]
+  movu                    m2, [srcq+src_strideq*2]
+  movu                    m3, [srcq+r5q]
+  lea                   srcq, [srcq+src_strideq*4]
+%ifidn %1, avg
+  pavgb                   m0, [dstq]
+  pavgb                   m1, [dstq+dst_strideq]
+  pavgb                   m2, [dstq+dst_strideq*2]
+  pavgb                   m3, [dstq+r6q]
+%endif
+  mova  [dstq              ], m0
+  mova  [dstq+dst_strideq  ], m1
+  mova  [dstq+dst_strideq*2], m2
+  mova  [dstq+r6q          ], m3
+  lea                   dstq, [dstq+dst_strideq*4]
+  sub                    r4d, 4
+  jnz .loop16
+  RET
+
+INIT_MMX sse
+.w8:
+  mov                    r4d, dword hm
+  lea                    r5q, [src_strideq*3]
+  lea                    r6q, [dst_strideq*3]
+.loop8:
+  movu                    m0, [srcq]
+  movu                    m1, [srcq+src_strideq]
+  movu                    m2, [srcq+src_strideq*2]
+  movu                    m3, [srcq+r5q]
+  lea                   srcq, [srcq+src_strideq*4]
+%ifidn %1, avg
+  pavgb                   m0, [dstq]
+  pavgb                   m1, [dstq+dst_strideq]
+  pavgb                   m2, [dstq+dst_strideq*2]
+  pavgb                   m3, [dstq+r6q]
+%endif
+  mova  [dstq              ], m0
+  mova  [dstq+dst_strideq  ], m1
+  mova  [dstq+dst_strideq*2], m2
+  mova  [dstq+r6q          ], m3
+  lea                   dstq, [dstq+dst_strideq*4]
+  sub                    r4d, 4
+  jnz .loop8
+  RET
+
+.w4:
+  mov                    r4d, dword hm
+  lea                    r5q, [src_strideq*3]
+  lea                    r6q, [dst_strideq*3]
+.loop4:
+  movh                    m0, [srcq]
+  movh                    m1, [srcq+src_strideq]
+  movh                    m2, [srcq+src_strideq*2]
+  movh                    m3, [srcq+r5q]
+  lea                   srcq, [srcq+src_strideq*4]
+%ifidn %1, avg
+  pavgb                   m0, [dstq]
+  pavgb                   m1, [dstq+dst_strideq]
+  pavgb                   m2, [dstq+dst_strideq*2]
+  pavgb                   m3, [dstq+r6q]
+%endif
+  movh  [dstq              ], m0
+  movh  [dstq+dst_strideq  ], m1
+  movh  [dstq+dst_strideq*2], m2
+  movh  [dstq+r6q          ], m3
+  lea                   dstq, [dstq+dst_strideq*4]
+  sub                    r4d, 4
+  jnz .loop4
+  RET
+%endmacro
+
+convolve_fn copy
+convolve_fn avg
diff --git a/vp9/common/x86/vp9_idct_intrin_sse2.c b/vp9/common/x86/vp9_idct_intrin_sse2.c
index 599dcff..4495b15 100644
--- a/vp9/common/x86/vp9_idct_intrin_sse2.c
+++ b/vp9/common/x86/vp9_idct_intrin_sse2.c
@@ -241,6 +241,155 @@
   _mm_storel_epi64((__m128i *)output, in);
 }
 
+static INLINE void transpose_4x4(__m128i *res) {
+  const __m128i tr0_0 = _mm_unpacklo_epi16(res[0], res[1]);
+  const __m128i tr0_1 = _mm_unpacklo_epi16(res[2], res[3]);
+  res[0] = _mm_unpacklo_epi32(tr0_0, tr0_1);
+  res[2] = _mm_unpackhi_epi32(tr0_0, tr0_1);
+
+  res[1] = _mm_unpackhi_epi64(res[0], res[0]);
+  res[3] = _mm_unpackhi_epi64(res[2], res[2]);
+}
+
+void idct4_1d_sse2(__m128i *in) {
+  const __m128i k__cospi_p16_p16 = pair_set_epi16(cospi_16_64, cospi_16_64);
+  const __m128i k__cospi_p16_m16 = pair_set_epi16(cospi_16_64, -cospi_16_64);
+  const __m128i k__cospi_p24_m08 = pair_set_epi16(cospi_24_64, -cospi_8_64);
+  const __m128i k__cospi_p08_p24 = pair_set_epi16(cospi_8_64, cospi_24_64);
+  const __m128i k__DCT_CONST_ROUNDING = _mm_set1_epi32(DCT_CONST_ROUNDING);
+  __m128i u[8], v[8];
+
+  transpose_4x4(in);
+  // stage 1
+  u[0] = _mm_unpacklo_epi16(in[0], in[2]);
+  u[1] = _mm_unpacklo_epi16(in[1], in[3]);
+  v[0] = _mm_madd_epi16(u[0], k__cospi_p16_p16);
+  v[1] = _mm_madd_epi16(u[0], k__cospi_p16_m16);
+  v[2] = _mm_madd_epi16(u[1], k__cospi_p24_m08);
+  v[3] = _mm_madd_epi16(u[1], k__cospi_p08_p24);
+
+  u[0] = _mm_add_epi32(v[0], k__DCT_CONST_ROUNDING);
+  u[1] = _mm_add_epi32(v[1], k__DCT_CONST_ROUNDING);
+  u[2] = _mm_add_epi32(v[2], k__DCT_CONST_ROUNDING);
+  u[3] = _mm_add_epi32(v[3], k__DCT_CONST_ROUNDING);
+
+  v[0] = _mm_srai_epi32(u[0], DCT_CONST_BITS);
+  v[1] = _mm_srai_epi32(u[1], DCT_CONST_BITS);
+  v[2] = _mm_srai_epi32(u[2], DCT_CONST_BITS);
+  v[3] = _mm_srai_epi32(u[3], DCT_CONST_BITS);
+
+  u[0] = _mm_packs_epi32(v[0], v[2]);
+  u[1] = _mm_packs_epi32(v[1], v[3]);
+  u[2] = _mm_unpackhi_epi64(u[0], u[0]);
+  u[3] = _mm_unpackhi_epi64(u[1], u[1]);
+
+  // stage 2
+  in[0] = _mm_add_epi16(u[0], u[3]);
+  in[1] = _mm_add_epi16(u[1], u[2]);
+  in[2] = _mm_sub_epi16(u[1], u[2]);
+  in[3] = _mm_sub_epi16(u[0], u[3]);
+}
+
+void iadst4_1d_sse2(__m128i *in) {
+  const __m128i k__sinpi_p01_p04 = pair_set_epi16(sinpi_1_9, sinpi_4_9);
+  const __m128i k__sinpi_p03_p02 = pair_set_epi16(sinpi_3_9, sinpi_2_9);
+  const __m128i k__sinpi_p02_m01 = pair_set_epi16(sinpi_2_9, -sinpi_1_9);
+  const __m128i k__sinpi_p03_m04 = pair_set_epi16(sinpi_3_9, -sinpi_4_9);
+  const __m128i k__sinpi_p03_p03 = _mm_set1_epi16(sinpi_3_9);
+  const __m128i kZero = _mm_set1_epi16(0);
+  const __m128i k__DCT_CONST_ROUNDING = _mm_set1_epi32(DCT_CONST_ROUNDING);
+  __m128i u[8], v[8], in7;
+
+  transpose_4x4(in);
+  in7 = _mm_add_epi16(in[0], in[3]);
+  in7 = _mm_sub_epi16(in7, in[2]);
+
+  u[0] = _mm_unpacklo_epi16(in[0], in[2]);
+  u[1] = _mm_unpacklo_epi16(in[1], in[3]);
+  u[2] = _mm_unpacklo_epi16(in7, kZero);
+  u[3] = _mm_unpacklo_epi16(in[1], kZero);
+
+  v[0] = _mm_madd_epi16(u[0], k__sinpi_p01_p04);  // s0 + s3
+  v[1] = _mm_madd_epi16(u[1], k__sinpi_p03_p02);  // s2 + s5
+  v[2] = _mm_madd_epi16(u[2], k__sinpi_p03_p03);  // x2
+  v[3] = _mm_madd_epi16(u[0], k__sinpi_p02_m01);  // s1 - s4
+  v[4] = _mm_madd_epi16(u[1], k__sinpi_p03_m04);  // s2 - s6
+  v[5] = _mm_madd_epi16(u[3], k__sinpi_p03_p03);  // s2
+
+  u[0] = _mm_add_epi32(v[0], v[1]);
+  u[1] = _mm_add_epi32(v[3], v[4]);
+  u[2] = v[2];
+  u[3] = _mm_add_epi32(u[0], u[1]);
+  u[4] = _mm_slli_epi32(v[5], 2);
+  u[5] = _mm_add_epi32(u[3], v[5]);
+  u[6] = _mm_sub_epi32(u[5], u[4]);
+
+  v[0] = _mm_add_epi32(u[0], k__DCT_CONST_ROUNDING);
+  v[1] = _mm_add_epi32(u[1], k__DCT_CONST_ROUNDING);
+  v[2] = _mm_add_epi32(u[2], k__DCT_CONST_ROUNDING);
+  v[3] = _mm_add_epi32(u[6], k__DCT_CONST_ROUNDING);
+
+  u[0] = _mm_srai_epi32(v[0], DCT_CONST_BITS);
+  u[1] = _mm_srai_epi32(v[1], DCT_CONST_BITS);
+  u[2] = _mm_srai_epi32(v[2], DCT_CONST_BITS);
+  u[3] = _mm_srai_epi32(v[3], DCT_CONST_BITS);
+
+  in[0] = _mm_packs_epi32(u[0], u[2]);
+  in[1] = _mm_packs_epi32(u[1], u[3]);
+  in[2] = _mm_unpackhi_epi64(in[0], in[0]);
+  in[3] = _mm_unpackhi_epi64(in[1], in[1]);
+}
+
+void vp9_short_iht4x4_add_sse2(int16_t *input, uint8_t *dest, int stride,
+                               int tx_type) {
+  __m128i in[4];
+  const __m128i zero = _mm_setzero_si128();
+  const __m128i eight = _mm_set1_epi16(8);
+
+  in[0] = _mm_loadl_epi64((__m128i *)input);
+  in[1] = _mm_loadl_epi64((__m128i *)(input + 4));
+  in[2] = _mm_loadl_epi64((__m128i *)(input + 8));
+  in[3] = _mm_loadl_epi64((__m128i *)(input + 12));
+
+  switch (tx_type) {
+    case 0:  // DCT_DCT
+      idct4_1d_sse2(in);
+      idct4_1d_sse2(in);
+      break;
+    case 1:  // ADST_DCT
+      idct4_1d_sse2(in);
+      iadst4_1d_sse2(in);
+      break;
+    case 2:  // DCT_ADST
+      iadst4_1d_sse2(in);
+      idct4_1d_sse2(in);
+      break;
+    case 3:  // ADST_ADST
+      iadst4_1d_sse2(in);
+      iadst4_1d_sse2(in);
+      break;
+    default:
+      assert(0);
+      break;
+  }
+
+  // Final round and shift
+  in[0] = _mm_add_epi16(in[0], eight);
+  in[1] = _mm_add_epi16(in[1], eight);
+  in[2] = _mm_add_epi16(in[2], eight);
+  in[3] = _mm_add_epi16(in[3], eight);
+
+  in[0] = _mm_srai_epi16(in[0], 4);
+  in[1] = _mm_srai_epi16(in[1], 4);
+  in[2] = _mm_srai_epi16(in[2], 4);
+  in[3] = _mm_srai_epi16(in[3], 4);
+
+  RECON_AND_STORE4X4(dest, in[0]);
+  RECON_AND_STORE4X4(dest, in[1]);
+  RECON_AND_STORE4X4(dest, in[2]);
+  RECON_AND_STORE4X4(dest, in[3]);
+}
+
 #define TRANSPOSE_8X8(in0, in1, in2, in3, in4, in5, in6, in7, \
                       out0, out1, out2, out3, out4, out5, out6, out7) \
   {                                                     \
diff --git a/vp9/common/x86/vp9_loopfilter_intrin_sse2.c b/vp9/common/x86/vp9_loopfilter_intrin_sse2.c
index 50f890a..a0dce5e 100644
--- a/vp9/common/x86/vp9_loopfilter_intrin_sse2.c
+++ b/vp9/common/x86/vp9_loopfilter_intrin_sse2.c
@@ -18,11 +18,11 @@
 extern loop_filter_uvfunction vp9_loop_filter_horizontal_edge_uv_sse2;
 extern loop_filter_uvfunction vp9_loop_filter_vertical_edge_uv_sse2;
 
-void vp9_mb_lpf_horizontal_edge_w_sse2(unsigned char *s,
-                                       int p,
-                                       const unsigned char *_blimit,
-                                       const unsigned char *_limit,
-                                       const unsigned char *_thresh) {
+void vp9_mb_lpf_horizontal_edge_w_sse2_8(unsigned char *s,
+                                         int p,
+                                         const unsigned char *_blimit,
+                                         const unsigned char *_limit,
+                                         const unsigned char *_thresh) {
   DECLARE_ALIGNED(16, unsigned char, flat2_op[7][8]);
   DECLARE_ALIGNED(16, unsigned char, flat2_oq[7][8]);
 
@@ -483,6 +483,490 @@
   }
 }
 
+void vp9_mb_lpf_horizontal_edge_w_sse2_16(unsigned char *s,
+                                          int p,
+                                          const unsigned char *_blimit,
+                                          const unsigned char *_limit,
+                                          const unsigned char *_thresh) {
+  DECLARE_ALIGNED(16, unsigned char, flat2_op[7][16]);
+  DECLARE_ALIGNED(16, unsigned char, flat2_oq[7][16]);
+
+  DECLARE_ALIGNED(16, unsigned char, flat_op[3][16]);
+  DECLARE_ALIGNED(16, unsigned char, flat_oq[3][16]);
+
+  DECLARE_ALIGNED(16, unsigned char, ap[8][16]);
+  DECLARE_ALIGNED(16, unsigned char, aq[8][16]);
+
+
+  __m128i mask, hev, flat, flat2;
+  const __m128i zero = _mm_set1_epi16(0);
+  const __m128i one = _mm_set1_epi8(1);
+  __m128i p7, p6, p5;
+  __m128i p4, p3, p2, p1, p0, q0, q1, q2, q3, q4;
+  __m128i q5, q6, q7;
+  int i = 0;
+  const unsigned int extended_thresh = _thresh[0] * 0x01010101u;
+  const unsigned int extended_limit  = _limit[0]  * 0x01010101u;
+  const unsigned int extended_blimit = _blimit[0] * 0x01010101u;
+  const __m128i thresh =
+      _mm_shuffle_epi32(_mm_cvtsi32_si128((int)extended_thresh), 0);
+  const __m128i limit =
+      _mm_shuffle_epi32(_mm_cvtsi32_si128((int)extended_limit), 0);
+  const __m128i blimit =
+      _mm_shuffle_epi32(_mm_cvtsi32_si128((int)extended_blimit), 0);
+
+  p4 = _mm_loadu_si128((__m128i *)(s - 5 * p));
+  p3 = _mm_loadu_si128((__m128i *)(s - 4 * p));
+  p2 = _mm_loadu_si128((__m128i *)(s - 3 * p));
+  p1 = _mm_loadu_si128((__m128i *)(s - 2 * p));
+  p0 = _mm_loadu_si128((__m128i *)(s - 1 * p));
+  q0 = _mm_loadu_si128((__m128i *)(s - 0 * p));
+  q1 = _mm_loadu_si128((__m128i *)(s + 1 * p));
+  q2 = _mm_loadu_si128((__m128i *)(s + 2 * p));
+  q3 = _mm_loadu_si128((__m128i *)(s + 3 * p));
+  q4 = _mm_loadu_si128((__m128i *)(s + 4 * p));
+
+  _mm_store_si128((__m128i *)ap[4], p4);
+  _mm_store_si128((__m128i *)ap[3], p3);
+  _mm_store_si128((__m128i *)ap[2], p2);
+  _mm_store_si128((__m128i *)ap[1], p1);
+  _mm_store_si128((__m128i *)ap[0], p0);
+  _mm_store_si128((__m128i *)aq[4], q4);
+  _mm_store_si128((__m128i *)aq[3], q3);
+  _mm_store_si128((__m128i *)aq[2], q2);
+  _mm_store_si128((__m128i *)aq[1], q1);
+  _mm_store_si128((__m128i *)aq[0], q0);
+
+
+  {
+    const __m128i abs_p1p0 = _mm_or_si128(_mm_subs_epu8(p1, p0),
+                                          _mm_subs_epu8(p0, p1));
+    const __m128i abs_q1q0 = _mm_or_si128(_mm_subs_epu8(q1, q0),
+                                          _mm_subs_epu8(q0, q1));
+    const __m128i fe = _mm_set1_epi8(0xfe);
+    const __m128i ff = _mm_cmpeq_epi8(abs_p1p0, abs_p1p0);
+    __m128i abs_p0q0 = _mm_or_si128(_mm_subs_epu8(p0, q0),
+                                    _mm_subs_epu8(q0, p0));
+    __m128i abs_p1q1 = _mm_or_si128(_mm_subs_epu8(p1, q1),
+                                    _mm_subs_epu8(q1, p1));
+    __m128i work;
+    flat = _mm_max_epu8(abs_p1p0, abs_q1q0);
+    hev = _mm_subs_epu8(flat, thresh);
+    hev = _mm_xor_si128(_mm_cmpeq_epi8(hev, zero), ff);
+
+    abs_p0q0 =_mm_adds_epu8(abs_p0q0, abs_p0q0);
+    abs_p1q1 = _mm_srli_epi16(_mm_and_si128(abs_p1q1, fe), 1);
+    mask = _mm_subs_epu8(_mm_adds_epu8(abs_p0q0, abs_p1q1), blimit);
+    mask = _mm_xor_si128(_mm_cmpeq_epi8(mask, zero), ff);
+    // mask |= (abs(p0 - q0) * 2 + abs(p1 - q1) / 2  > blimit) * -1;
+    mask = _mm_max_epu8(flat, mask);
+    // mask |= (abs(p1 - p0) > limit) * -1;
+    // mask |= (abs(q1 - q0) > limit) * -1;
+    work = _mm_max_epu8(_mm_or_si128(_mm_subs_epu8(p2, p1),
+                                     _mm_subs_epu8(p1, p2)),
+                         _mm_or_si128(_mm_subs_epu8(p3, p2),
+                                      _mm_subs_epu8(p2, p3)));
+    mask = _mm_max_epu8(work, mask);
+    work = _mm_max_epu8(_mm_or_si128(_mm_subs_epu8(q2, q1),
+                                     _mm_subs_epu8(q1, q2)),
+                         _mm_or_si128(_mm_subs_epu8(q3, q2),
+                                      _mm_subs_epu8(q2, q3)));
+    mask = _mm_max_epu8(work, mask);
+    mask = _mm_subs_epu8(mask, limit);
+    mask = _mm_cmpeq_epi8(mask, zero);
+  }
+
+  // lp filter
+  {
+    const __m128i t4 = _mm_set1_epi8(4);
+    const __m128i t3 = _mm_set1_epi8(3);
+    const __m128i t80 = _mm_set1_epi8(0x80);
+    const __m128i te0 = _mm_set1_epi8(0xe0);
+    const __m128i t1f = _mm_set1_epi8(0x1f);
+    const __m128i t1 = _mm_set1_epi8(0x1);
+    const __m128i t7f = _mm_set1_epi8(0x7f);
+
+    __m128i ps1 = _mm_xor_si128(p1, t80);
+    __m128i ps0 = _mm_xor_si128(p0, t80);
+    __m128i qs0 = _mm_xor_si128(q0, t80);
+    __m128i qs1 = _mm_xor_si128(q1, t80);
+    __m128i filt;
+    __m128i work_a;
+    __m128i filter1, filter2;
+
+    filt = _mm_and_si128(_mm_subs_epi8(ps1, qs1), hev);
+    work_a = _mm_subs_epi8(qs0, ps0);
+    filt = _mm_adds_epi8(filt, work_a);
+    filt = _mm_adds_epi8(filt, work_a);
+    filt = _mm_adds_epi8(filt, work_a);
+    /* (vp9_filter + 3 * (qs0 - ps0)) & mask */
+    filt = _mm_and_si128(filt, mask);
+
+    filter1 = _mm_adds_epi8(filt, t4);
+    filter2 = _mm_adds_epi8(filt, t3);
+
+    /* Filter1 >> 3 */
+    work_a = _mm_cmpgt_epi8(zero, filter1);
+    filter1 = _mm_srli_epi16(filter1, 3);
+    work_a = _mm_and_si128(work_a, te0);
+    filter1 = _mm_and_si128(filter1, t1f);
+    filter1 = _mm_or_si128(filter1, work_a);
+    qs0 = _mm_xor_si128(_mm_subs_epi8(qs0, filter1), t80);
+
+    /* Filter2 >> 3 */
+    work_a = _mm_cmpgt_epi8(zero, filter2);
+    filter2 = _mm_srli_epi16(filter2, 3);
+    work_a = _mm_and_si128(work_a, te0);
+    filter2 = _mm_and_si128(filter2, t1f);
+    filter2 = _mm_or_si128(filter2, work_a);
+    ps0 = _mm_xor_si128(_mm_adds_epi8(ps0, filter2), t80);
+
+    /* filt >> 1 */
+    filt = _mm_adds_epi8(filter1, t1);
+    work_a = _mm_cmpgt_epi8(zero, filt);
+    filt = _mm_srli_epi16(filt, 1);
+    work_a = _mm_and_si128(work_a, t80);
+    filt = _mm_and_si128(filt, t7f);
+    filt = _mm_or_si128(filt, work_a);
+    filt = _mm_andnot_si128(hev, filt);
+    ps1 = _mm_xor_si128(_mm_adds_epi8(ps1, filt), t80);
+    qs1 = _mm_xor_si128(_mm_subs_epi8(qs1, filt), t80);
+    // loopfilter done
+
+    {
+      __m128i work;
+      work = _mm_max_epu8(_mm_or_si128(_mm_subs_epu8(p2, p0),
+                                       _mm_subs_epu8(p0, p2)),
+                           _mm_or_si128(_mm_subs_epu8(q2, q0),
+                                        _mm_subs_epu8(q0, q2)));
+      flat = _mm_max_epu8(work, flat);
+      work = _mm_max_epu8(_mm_or_si128(_mm_subs_epu8(p3, p0),
+                                       _mm_subs_epu8(p0, p3)),
+                           _mm_or_si128(_mm_subs_epu8(q3, q0),
+                                        _mm_subs_epu8(q0, q3)));
+      flat = _mm_max_epu8(work, flat);
+      work = _mm_max_epu8(_mm_or_si128(_mm_subs_epu8(p4, p0),
+                                       _mm_subs_epu8(p0, p4)),
+                           _mm_or_si128(_mm_subs_epu8(q4, q0),
+                                        _mm_subs_epu8(q0, q4)));
+      flat = _mm_subs_epu8(flat, one);
+      flat = _mm_cmpeq_epi8(flat, zero);
+      flat = _mm_and_si128(flat, mask);
+
+      p5 = _mm_loadu_si128((__m128i *)(s - 6 * p));
+      q5 = _mm_loadu_si128((__m128i *)(s + 5 * p));
+      flat2 = _mm_max_epu8(_mm_or_si128(_mm_subs_epu8(p5, p0),
+                                       _mm_subs_epu8(p0, p5)),
+                           _mm_or_si128(_mm_subs_epu8(q5, q0),
+                                        _mm_subs_epu8(q0, q5)));
+      _mm_store_si128((__m128i *)ap[5], p5);
+      _mm_store_si128((__m128i *)aq[5], q5);
+      flat2 = _mm_max_epu8(work, flat2);
+      p6 = _mm_loadu_si128((__m128i *)(s - 7 * p));
+      q6 = _mm_loadu_si128((__m128i *)(s + 6 * p));
+      work = _mm_max_epu8(_mm_or_si128(_mm_subs_epu8(p6, p0),
+                                       _mm_subs_epu8(p0, p6)),
+                           _mm_or_si128(_mm_subs_epu8(q6, q0),
+                                        _mm_subs_epu8(q0, q6)));
+      _mm_store_si128((__m128i *)ap[6], p6);
+      _mm_store_si128((__m128i *)aq[6], q6);
+      flat2 = _mm_max_epu8(work, flat2);
+
+      p7 = _mm_loadu_si128((__m128i *)(s - 8 * p));
+      q7 = _mm_loadu_si128((__m128i *)(s + 7 * p));
+      work = _mm_max_epu8(_mm_or_si128(_mm_subs_epu8(p7, p0),
+                                       _mm_subs_epu8(p0, p7)),
+                           _mm_or_si128(_mm_subs_epu8(q7, q0),
+                                        _mm_subs_epu8(q0, q7)));
+      _mm_store_si128((__m128i *)ap[7], p7);
+      _mm_store_si128((__m128i *)aq[7], q7);
+      flat2 = _mm_max_epu8(work, flat2);
+      flat2 = _mm_subs_epu8(flat2, one);
+      flat2 = _mm_cmpeq_epi8(flat2, zero);
+      flat2 = _mm_and_si128(flat2, flat);  // flat2 & flat & mask
+    }
+
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    // flat and wide flat calculations
+    {
+      const __m128i eight = _mm_set1_epi16(8);
+      const __m128i four = _mm_set1_epi16(4);
+      __m128i temp_flat2 = flat2;
+      unsigned char *src = s;
+      int i = 0;
+      do {
+        __m128i workp_shft;
+        __m128i a, b, c;
+
+        unsigned int off = i * 8;
+        p7 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i *)(ap[7] + off)), zero);
+        p6 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i *)(ap[6] + off)), zero);
+        p5 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i *)(ap[5] + off)), zero);
+        p4 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i *)(ap[4] + off)), zero);
+        p3 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i *)(ap[3] + off)), zero);
+        p2 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i *)(ap[2] + off)), zero);
+        p1 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i *)(ap[1] + off)), zero);
+        p0 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i *)(ap[0] + off)), zero);
+        q0 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i *)(aq[0] + off)), zero);
+        q1 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i *)(aq[1] + off)), zero);
+        q2 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i *)(aq[2] + off)), zero);
+        q3 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i *)(aq[3] + off)), zero);
+        q4 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i *)(aq[4] + off)), zero);
+        q5 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i *)(aq[5] + off)), zero);
+        q6 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i *)(aq[6] + off)), zero);
+        q7 = _mm_unpacklo_epi8(_mm_loadl_epi64((__m128i *)(aq[7] + off)), zero);
+
+        c = _mm_sub_epi16(_mm_slli_epi16(p7, 3), p7);  // p7 * 7
+        c = _mm_add_epi16(_mm_slli_epi16(p6, 1), _mm_add_epi16(p4, c));
+
+        b = _mm_add_epi16(_mm_add_epi16(p3, four), _mm_add_epi16(p3, p2));
+        a = _mm_add_epi16(p3, _mm_add_epi16(p2, p1));
+        a = _mm_add_epi16(_mm_add_epi16(p0, q0), a);
+
+        _mm_storel_epi64((__m128i *)&flat_op[2][i*8],
+                         _mm_packus_epi16(_mm_srli_epi16(_mm_add_epi16(a, b), 3)
+                                          , b));
+
+        c = _mm_add_epi16(_mm_add_epi16(p5, eight), c);
+        workp_shft = _mm_srli_epi16(_mm_add_epi16(a, c), 4);
+        _mm_storel_epi64((__m128i *)&flat2_op[6][i*8],
+                         _mm_packus_epi16(workp_shft, workp_shft));
+
+        a = _mm_add_epi16(q1, a);
+        b = _mm_add_epi16(_mm_sub_epi16(b, _mm_add_epi16(p3, p2)), p1);
+        _mm_storel_epi64((__m128i *)&flat_op[1][i*8],
+                         _mm_packus_epi16(_mm_srli_epi16(_mm_add_epi16(a, b), 3)
+                                          , b));
+
+        c = _mm_add_epi16(_mm_sub_epi16(c, _mm_add_epi16(p7, p6)), p5);
+        workp_shft = _mm_srli_epi16(_mm_add_epi16(a, c), 4);
+        _mm_storel_epi64((__m128i *)&flat2_op[5][i*8],
+                         _mm_packus_epi16(workp_shft, workp_shft));
+
+        a = _mm_add_epi16(q2, a);
+        b = _mm_add_epi16(_mm_sub_epi16(b, _mm_add_epi16(p3, p1)), p0);
+        _mm_storel_epi64((__m128i *)&flat_op[0][i*8],
+                         _mm_packus_epi16(_mm_srli_epi16(_mm_add_epi16(a, b), 3)
+                                          , b));
+
+        c = _mm_add_epi16(_mm_sub_epi16(c, _mm_add_epi16(p7, p5)), p4);
+        workp_shft = _mm_srli_epi16(_mm_add_epi16(a, c), 4);
+        _mm_storel_epi64((__m128i *)&flat2_op[4][i*8],
+                         _mm_packus_epi16(workp_shft, workp_shft));
+
+        a = _mm_add_epi16(q3, a);
+        b = _mm_add_epi16(_mm_sub_epi16(b, _mm_add_epi16(p3, p0)), q0);
+        _mm_storel_epi64((__m128i *)&flat_oq[0][i*8],
+                         _mm_packus_epi16(_mm_srli_epi16(_mm_add_epi16(a, b), 3)
+                                          , b));
+
+        c = _mm_add_epi16(_mm_sub_epi16(c, _mm_add_epi16(p7, p4)), p3);
+        workp_shft = _mm_srli_epi16(_mm_add_epi16(a, c), 4);
+        _mm_storel_epi64((__m128i *)&flat2_op[3][i*8],
+                         _mm_packus_epi16(workp_shft, workp_shft));
+
+        b = _mm_add_epi16(q3, b);
+        b = _mm_add_epi16(_mm_sub_epi16(b, _mm_add_epi16(p2, q0)), q1);
+        _mm_storel_epi64((__m128i *)&flat_oq[1][i*8],
+                         _mm_packus_epi16(_mm_srli_epi16(_mm_add_epi16(a, b), 3)
+                                          , b));
+
+        c = _mm_add_epi16(q4, c);
+        c = _mm_add_epi16(_mm_sub_epi16(c, _mm_add_epi16(p7, p3)), p2);
+        workp_shft = _mm_srli_epi16(_mm_add_epi16(a, c), 4);
+        _mm_storel_epi64((__m128i *)&flat2_op[2][i*8],
+                         _mm_packus_epi16(workp_shft, workp_shft));
+
+        b = _mm_add_epi16(q3, b);
+        b = _mm_add_epi16(_mm_sub_epi16(b, _mm_add_epi16(p1, q1)), q2);
+        _mm_storel_epi64((__m128i *)&flat_oq[2][i*8],
+                         _mm_packus_epi16(_mm_srli_epi16(_mm_add_epi16(a, b), 3)
+                                          , b));
+        a = _mm_add_epi16(q5, a);
+        c = _mm_add_epi16(_mm_sub_epi16(c, _mm_add_epi16(p7, p2)), p1);
+        workp_shft = _mm_srli_epi16(_mm_add_epi16(a, c), 4);
+        _mm_storel_epi64((__m128i *)&flat2_op[1][i*8],
+                         _mm_packus_epi16(workp_shft, workp_shft));
+
+        a = _mm_add_epi16(q6, a);
+        c = _mm_add_epi16(_mm_sub_epi16(c, _mm_add_epi16(p7, p1)), p0);
+        workp_shft = _mm_srli_epi16(_mm_add_epi16(a, c), 4);
+        _mm_storel_epi64((__m128i *)&flat2_op[0][i*8],
+                         _mm_packus_epi16(workp_shft, workp_shft));
+
+        a = _mm_add_epi16(q7, a);
+        c = _mm_add_epi16(_mm_sub_epi16(c, _mm_add_epi16(p7, p0)), q0);
+        workp_shft = _mm_srli_epi16(_mm_add_epi16(a, c), 4);
+        _mm_storel_epi64((__m128i *)&flat2_oq[0][i*8],
+                         _mm_packus_epi16(workp_shft, workp_shft));
+
+        a = _mm_add_epi16(q7, a);
+        c = _mm_add_epi16(_mm_sub_epi16(c, _mm_add_epi16(p6, q0)), q1);
+        workp_shft = _mm_srli_epi16(_mm_add_epi16(a, c), 4);
+        _mm_storel_epi64((__m128i *)&flat2_oq[1][i*8],
+                         _mm_packus_epi16(workp_shft, workp_shft));
+
+        a = _mm_add_epi16(q7, a);
+        c = _mm_add_epi16(_mm_sub_epi16(c, _mm_add_epi16(p5, q1)), q2);
+        workp_shft = _mm_srli_epi16(_mm_add_epi16(a, c), 4);
+        _mm_storel_epi64((__m128i *)&flat2_oq[2][i*8],
+                         _mm_packus_epi16(workp_shft, workp_shft));
+
+        a = _mm_add_epi16(q7, a);
+        c = _mm_add_epi16(_mm_sub_epi16(c, _mm_add_epi16(p4, q2)), q3);
+        workp_shft = _mm_srli_epi16(_mm_add_epi16(a, c), 4);
+        _mm_storel_epi64((__m128i *)&flat2_oq[3][i*8],
+                         _mm_packus_epi16(workp_shft, workp_shft));
+
+        a = _mm_add_epi16(q7, a);
+        c = _mm_add_epi16(_mm_sub_epi16(c, _mm_add_epi16(p3, q3)), q4);
+        workp_shft = _mm_srli_epi16(_mm_add_epi16(a, c), 4);
+        _mm_storel_epi64((__m128i *)&flat2_oq[4][i*8],
+                         _mm_packus_epi16(workp_shft, workp_shft));
+
+        a = _mm_add_epi16(q7, a);
+        c = _mm_add_epi16(_mm_sub_epi16(c, _mm_add_epi16(p2, q4)), q5);
+        workp_shft = _mm_srli_epi16(_mm_add_epi16(a, c), 4);
+        _mm_storel_epi64((__m128i *)&flat2_oq[5][i*8],
+                         _mm_packus_epi16(workp_shft, workp_shft));
+
+        a = _mm_add_epi16(q7, a);
+        c = _mm_add_epi16(_mm_sub_epi16(c, _mm_add_epi16(p1, q5)), q6);
+        workp_shft = _mm_srli_epi16(_mm_add_epi16(a, c), 4);
+        _mm_storel_epi64((__m128i *)&flat2_oq[6][i*8],
+                         _mm_packus_epi16(workp_shft, workp_shft));
+
+        temp_flat2 = _mm_srli_si128(temp_flat2, 8);
+        src += 8;
+      } while (++i < 2);
+    }
+    // wide flat
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+    work_a = _mm_load_si128((__m128i *)ap[2]);
+    p2 = _mm_load_si128((__m128i *)flat_op[2]);
+    work_a = _mm_andnot_si128(flat, work_a);
+    p2 = _mm_and_si128(flat, p2);
+    p2 = _mm_or_si128(work_a, p2);
+    _mm_store_si128((__m128i *)flat_op[2], p2);
+
+    p1 = _mm_load_si128((__m128i *)flat_op[1]);
+    work_a = _mm_andnot_si128(flat, ps1);
+    p1 = _mm_and_si128(flat, p1);
+    p1 = _mm_or_si128(work_a, p1);
+    _mm_store_si128((__m128i *)flat_op[1], p1);
+
+    p0 = _mm_load_si128((__m128i *)flat_op[0]);
+    work_a = _mm_andnot_si128(flat, ps0);
+    p0 = _mm_and_si128(flat, p0);
+    p0 = _mm_or_si128(work_a, p0);
+    _mm_store_si128((__m128i *)flat_op[0], p0);
+
+    q0 = _mm_load_si128((__m128i *)flat_oq[0]);
+    work_a = _mm_andnot_si128(flat, qs0);
+    q0 = _mm_and_si128(flat, q0);
+    q0 = _mm_or_si128(work_a, q0);
+    _mm_store_si128((__m128i *)flat_oq[0], q0);
+
+    q1 = _mm_load_si128((__m128i *)flat_oq[1]);
+    work_a = _mm_andnot_si128(flat, qs1);
+    q1 = _mm_and_si128(flat, q1);
+    q1 = _mm_or_si128(work_a, q1);
+    _mm_store_si128((__m128i *)flat_oq[1], q1);
+
+    work_a = _mm_load_si128((__m128i *)aq[2]);
+    q2 = _mm_load_si128((__m128i *)flat_oq[2]);
+    work_a = _mm_andnot_si128(flat, work_a);
+    q2 = _mm_and_si128(flat, q2);
+    q2 = _mm_or_si128(work_a, q2);
+    _mm_store_si128((__m128i *)flat_oq[2], q2);
+
+    // write out op6 - op3
+    {
+      unsigned char *dst = (s - 7 * p);
+      for (i = 6; i > 2; i--) {
+        __m128i flat2_output;
+        work_a = _mm_load_si128((__m128i *)ap[i]);
+        flat2_output = _mm_load_si128((__m128i *)flat2_op[i]);
+        work_a = _mm_andnot_si128(flat2, work_a);
+        flat2_output = _mm_and_si128(flat2, flat2_output);
+        work_a = _mm_or_si128(work_a, flat2_output);
+        _mm_storeu_si128((__m128i *)dst, work_a);
+        dst += p;
+      }
+    }
+
+    work_a = _mm_load_si128((__m128i *)flat_op[2]);
+    p2 = _mm_load_si128((__m128i *)flat2_op[2]);
+    work_a = _mm_andnot_si128(flat2, work_a);
+    p2 = _mm_and_si128(flat2, p2);
+    p2 = _mm_or_si128(work_a, p2);
+    _mm_storeu_si128((__m128i *)(s - 3 * p), p2);
+
+    work_a = _mm_load_si128((__m128i *)flat_op[1]);
+    p1 = _mm_load_si128((__m128i *)flat2_op[1]);
+    work_a = _mm_andnot_si128(flat2, work_a);
+    p1 = _mm_and_si128(flat2, p1);
+    p1 = _mm_or_si128(work_a, p1);
+    _mm_storeu_si128((__m128i *)(s - 2 * p), p1);
+
+    work_a = _mm_load_si128((__m128i *)flat_op[0]);
+    p0 = _mm_load_si128((__m128i *)flat2_op[0]);
+    work_a = _mm_andnot_si128(flat2, work_a);
+    p0 = _mm_and_si128(flat2, p0);
+    p0 = _mm_or_si128(work_a, p0);
+    _mm_storeu_si128((__m128i *)(s - 1 * p), p0);
+
+    work_a = _mm_load_si128((__m128i *)flat_oq[0]);
+    q0 = _mm_load_si128((__m128i *)flat2_oq[0]);
+    work_a = _mm_andnot_si128(flat2, work_a);
+    q0 = _mm_and_si128(flat2, q0);
+    q0 = _mm_or_si128(work_a, q0);
+    _mm_storeu_si128((__m128i *)(s - 0 * p), q0);
+
+    work_a = _mm_load_si128((__m128i *)flat_oq[1]);
+    q1 = _mm_load_si128((__m128i *)flat2_oq[1]);
+    work_a = _mm_andnot_si128(flat2, work_a);
+    q1 = _mm_and_si128(flat2, q1);
+    q1 = _mm_or_si128(work_a, q1);
+    _mm_storeu_si128((__m128i *)(s + 1 * p), q1);
+
+    work_a = _mm_load_si128((__m128i *)flat_oq[2]);
+    q2 = _mm_load_si128((__m128i *)flat2_oq[2]);
+    work_a = _mm_andnot_si128(flat2, work_a);
+    q2 = _mm_and_si128(flat2, q2);
+    q2 = _mm_or_si128(work_a, q2);
+    _mm_storeu_si128((__m128i *)(s + 2 * p), q2);
+
+    // write out oq3 - oq7
+    {
+      unsigned char *dst = (s + 3 * p);
+      for (i = 3; i < 7; i++) {
+        __m128i flat2_output;
+        work_a = _mm_load_si128((__m128i *)aq[i]);
+        flat2_output = _mm_load_si128((__m128i *)flat2_oq[i]);
+        work_a = _mm_andnot_si128(flat2, work_a);
+        flat2_output = _mm_and_si128(flat2, flat2_output);
+        work_a = _mm_or_si128(work_a, flat2_output);
+        _mm_storeu_si128((__m128i *)dst, work_a);
+        dst += p;
+      }
+    }
+  }
+}
+
+void vp9_mb_lpf_horizontal_edge_w_sse2(unsigned char *s,
+                                       int p,
+                                       const unsigned char *_blimit,
+                                       const unsigned char *_limit,
+                                       const unsigned char *_thresh,
+                                       int count) {
+  if (count == 1)
+    vp9_mb_lpf_horizontal_edge_w_sse2_8(s, p, _blimit, _limit, _thresh);
+  else
+    vp9_mb_lpf_horizontal_edge_w_sse2_16(s, p, _blimit, _limit, _thresh);
+}
+
 void vp9_mbloop_filter_horizontal_edge_sse2(unsigned char *s,
                                             int p,
                                             const unsigned char *_blimit,
@@ -972,7 +1456,7 @@
 
   /* Loop filtering */
   vp9_mb_lpf_horizontal_edge_w_sse2(t_dst + 8 * 16, 16, blimit, limit,
-                                           thresh);
+                                    thresh, 1);
 
   src[0] = t_dst;
   src[1] = t_dst + 8 * 16;
diff --git a/vp9/common/x86/vp9_recon_mmx.asm b/vp9/common/x86/vp9_recon_mmx.asm
deleted file mode 100644
index 6fbbe48..0000000
--- a/vp9/common/x86/vp9_recon_mmx.asm
+++ /dev/null
@@ -1,272 +0,0 @@
-;
-;  Copyright (c) 2010 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_ports/x86_abi_support.asm"
-;void copy_mem8x8_mmx(
-;    unsigned char *src,
-;    int src_stride,
-;    unsigned char *dst,
-;    int dst_stride
-;    )
-global sym(vp9_copy_mem8x8_mmx) PRIVATE
-sym(vp9_copy_mem8x8_mmx):
-    push        rbp
-    mov         rbp, rsp
-    SHADOW_ARGS_TO_STACK 4
-    push        rsi
-    push        rdi
-    ; end prolog
-
-        mov         rsi,        arg(0) ;src;
-        movq        mm0,        [rsi]
-
-        movsxd      rax,        dword ptr arg(1) ;src_stride;
-        mov         rdi,        arg(2) ;dst;
-
-        movq        mm1,        [rsi+rax]
-        movq        mm2,        [rsi+rax*2]
-
-        movsxd      rcx,        dword ptr arg(3) ;dst_stride
-        lea         rsi,        [rsi+rax*2]
-
-        movq        [rdi],      mm0
-        add         rsi,        rax
-
-        movq        [rdi+rcx],      mm1
-        movq        [rdi+rcx*2],    mm2
-
-
-        lea         rdi,        [rdi+rcx*2]
-        movq        mm3,        [rsi]
-
-        add         rdi,        rcx
-        movq        mm4,        [rsi+rax]
-
-        movq        mm5,        [rsi+rax*2]
-        movq        [rdi],      mm3
-
-        lea         rsi,        [rsi+rax*2]
-        movq        [rdi+rcx],  mm4
-
-        movq        [rdi+rcx*2],    mm5
-        lea         rdi,        [rdi+rcx*2]
-
-        movq        mm0,        [rsi+rax]
-        movq        mm1,        [rsi+rax*2]
-
-        movq        [rdi+rcx],  mm0
-        movq        [rdi+rcx*2],mm1
-
-    ; begin epilog
-    pop rdi
-    pop rsi
-    UNSHADOW_ARGS
-    pop         rbp
-    ret
-
-
-;void copy_mem8x4_mmx(
-;    unsigned char *src,
-;    int src_stride,
-;    unsigned char *dst,
-;    int dst_stride
-;    )
-global sym(vp9_copy_mem8x4_mmx) PRIVATE
-sym(vp9_copy_mem8x4_mmx):
-    push        rbp
-    mov         rbp, rsp
-    SHADOW_ARGS_TO_STACK 4
-    push        rsi
-    push        rdi
-    ; end prolog
-
-        mov         rsi,        arg(0) ;src;
-        movq        mm0,        [rsi]
-
-        movsxd      rax,        dword ptr arg(1) ;src_stride;
-        mov         rdi,        arg(2) ;dst;
-
-        movq        mm1,        [rsi+rax]
-        movq        mm2,        [rsi+rax*2]
-
-        movsxd      rcx,        dword ptr arg(3) ;dst_stride
-        lea         rsi,        [rsi+rax*2]
-
-        movq        [rdi],      mm0
-        movq        [rdi+rcx],      mm1
-
-        movq        [rdi+rcx*2],    mm2
-        lea         rdi,        [rdi+rcx*2]
-
-        movq        mm3,        [rsi+rax]
-        movq        [rdi+rcx],      mm3
-
-    ; begin epilog
-    pop rdi
-    pop rsi
-    UNSHADOW_ARGS
-    pop         rbp
-    ret
-
-
-;void copy_mem16x16_mmx(
-;    unsigned char *src,
-;    int src_stride,
-;    unsigned char *dst,
-;    int dst_stride
-;    )
-global sym(vp9_copy_mem16x16_mmx) PRIVATE
-sym(vp9_copy_mem16x16_mmx):
-    push        rbp
-    mov         rbp, rsp
-    SHADOW_ARGS_TO_STACK 4
-    push        rsi
-    push        rdi
-    ; end prolog
-
-        mov         rsi,        arg(0) ;src;
-        movsxd      rax,        dword ptr arg(1) ;src_stride;
-
-        mov         rdi,        arg(2) ;dst;
-        movsxd      rcx,        dword ptr arg(3) ;dst_stride
-
-        movq        mm0,            [rsi]
-        movq        mm3,            [rsi+8];
-
-        movq        mm1,            [rsi+rax]
-        movq        mm4,            [rsi+rax+8]
-
-        movq        mm2,            [rsi+rax*2]
-        movq        mm5,            [rsi+rax*2+8]
-
-        lea         rsi,            [rsi+rax*2]
-        add         rsi,            rax
-
-        movq        [rdi],          mm0
-        movq        [rdi+8],        mm3
-
-        movq        [rdi+rcx],      mm1
-        movq        [rdi+rcx+8],    mm4
-
-        movq        [rdi+rcx*2],    mm2
-        movq        [rdi+rcx*2+8],  mm5
-
-        lea         rdi,            [rdi+rcx*2]
-        add         rdi,            rcx
-
-        movq        mm0,            [rsi]
-        movq        mm3,            [rsi+8];
-
-        movq        mm1,            [rsi+rax]
-        movq        mm4,            [rsi+rax+8]
-
-        movq        mm2,            [rsi+rax*2]
-        movq        mm5,            [rsi+rax*2+8]
-
-        lea         rsi,            [rsi+rax*2]
-        add         rsi,            rax
-
-        movq        [rdi],          mm0
-        movq        [rdi+8],        mm3
-
-        movq        [rdi+rcx],      mm1
-        movq        [rdi+rcx+8],    mm4
-
-        movq        [rdi+rcx*2],    mm2
-        movq        [rdi+rcx*2+8],  mm5
-
-        lea         rdi,            [rdi+rcx*2]
-        add         rdi,            rcx
-
-        movq        mm0,            [rsi]
-        movq        mm3,            [rsi+8];
-
-        movq        mm1,            [rsi+rax]
-        movq        mm4,            [rsi+rax+8]
-
-        movq        mm2,            [rsi+rax*2]
-        movq        mm5,            [rsi+rax*2+8]
-
-        lea         rsi,            [rsi+rax*2]
-        add         rsi,            rax
-
-        movq        [rdi],          mm0
-        movq        [rdi+8],        mm3
-
-        movq        [rdi+rcx],      mm1
-        movq        [rdi+rcx+8],    mm4
-
-        movq        [rdi+rcx*2],    mm2
-        movq        [rdi+rcx*2+8],  mm5
-
-        lea         rdi,            [rdi+rcx*2]
-        add         rdi,            rcx
-
-        movq        mm0,            [rsi]
-        movq        mm3,            [rsi+8];
-
-        movq        mm1,            [rsi+rax]
-        movq        mm4,            [rsi+rax+8]
-
-        movq        mm2,            [rsi+rax*2]
-        movq        mm5,            [rsi+rax*2+8]
-
-        lea         rsi,            [rsi+rax*2]
-        add         rsi,            rax
-
-        movq        [rdi],          mm0
-        movq        [rdi+8],        mm3
-
-        movq        [rdi+rcx],      mm1
-        movq        [rdi+rcx+8],    mm4
-
-        movq        [rdi+rcx*2],    mm2
-        movq        [rdi+rcx*2+8],  mm5
-
-        lea         rdi,            [rdi+rcx*2]
-        add         rdi,            rcx
-
-        movq        mm0,            [rsi]
-        movq        mm3,            [rsi+8];
-
-        movq        mm1,            [rsi+rax]
-        movq        mm4,            [rsi+rax+8]
-
-        movq        mm2,            [rsi+rax*2]
-        movq        mm5,            [rsi+rax*2+8]
-
-        lea         rsi,            [rsi+rax*2]
-        add         rsi,            rax
-
-        movq        [rdi],          mm0
-        movq        [rdi+8],        mm3
-
-        movq        [rdi+rcx],      mm1
-        movq        [rdi+rcx+8],    mm4
-
-        movq        [rdi+rcx*2],    mm2
-        movq        [rdi+rcx*2+8],  mm5
-
-        lea         rdi,            [rdi+rcx*2]
-        add         rdi,            rcx
-
-        movq        mm0,            [rsi]
-        movq        mm3,            [rsi+8];
-
-        movq        [rdi],          mm0
-        movq        [rdi+8],        mm3
-
-    ; begin epilog
-    pop rdi
-    pop rsi
-    UNSHADOW_ARGS
-    pop         rbp
-    ret
diff --git a/vp9/common/x86/vp9_recon_sse2.asm b/vp9/common/x86/vp9_recon_sse2.asm
deleted file mode 100644
index f7cc611..0000000
--- a/vp9/common/x86/vp9_recon_sse2.asm
+++ /dev/null
@@ -1,115 +0,0 @@
-;
-;  Copyright (c) 2010 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_ports/x86_abi_support.asm"
-;void copy_mem16x16_sse2(
-;    unsigned char *src,
-;    int src_stride,
-;    unsigned char *dst,
-;    int dst_stride
-;    )
-global sym(vp9_copy_mem16x16_sse2) PRIVATE
-sym(vp9_copy_mem16x16_sse2):
-    push        rbp
-    mov         rbp, rsp
-    SHADOW_ARGS_TO_STACK 4
-    push        rsi
-    push        rdi
-    ; end prolog
-
-        mov         rsi,        arg(0) ;src;
-        movdqu      xmm0,       [rsi]
-
-        movsxd      rax,        dword ptr arg(1) ;src_stride;
-        mov         rdi,        arg(2) ;dst;
-
-        movdqu      xmm1,       [rsi+rax]
-        movdqu      xmm2,       [rsi+rax*2]
-
-        movsxd      rcx,        dword ptr arg(3) ;dst_stride
-        lea         rsi,        [rsi+rax*2]
-
-        movdqa      [rdi],      xmm0
-        add         rsi,        rax
-
-        movdqa      [rdi+rcx],  xmm1
-        movdqa      [rdi+rcx*2],xmm2
-
-        lea         rdi,        [rdi+rcx*2]
-        movdqu      xmm3,       [rsi]
-
-        add         rdi,        rcx
-        movdqu      xmm4,       [rsi+rax]
-
-        movdqu      xmm5,       [rsi+rax*2]
-        lea         rsi,        [rsi+rax*2]
-
-        movdqa      [rdi],  xmm3
-        add         rsi,        rax
-
-        movdqa      [rdi+rcx],  xmm4
-        movdqa      [rdi+rcx*2],xmm5
-
-        lea         rdi,        [rdi+rcx*2]
-        movdqu      xmm0,       [rsi]
-
-        add         rdi,        rcx
-        movdqu      xmm1,       [rsi+rax]
-
-        movdqu      xmm2,       [rsi+rax*2]
-        lea         rsi,        [rsi+rax*2]
-
-        movdqa      [rdi],      xmm0
-        add         rsi,        rax
-
-        movdqa      [rdi+rcx],  xmm1
-
-        movdqa      [rdi+rcx*2],    xmm2
-        movdqu      xmm3,       [rsi]
-
-        movdqu      xmm4,       [rsi+rax]
-        lea         rdi,        [rdi+rcx*2]
-
-        add         rdi,        rcx
-        movdqu      xmm5,       [rsi+rax*2]
-
-        lea         rsi,        [rsi+rax*2]
-        movdqa      [rdi],  xmm3
-
-        add         rsi,        rax
-        movdqa      [rdi+rcx],  xmm4
-
-        movdqa      [rdi+rcx*2],xmm5
-        movdqu      xmm0,       [rsi]
-
-        lea         rdi,        [rdi+rcx*2]
-        movdqu      xmm1,       [rsi+rax]
-
-        add         rdi,        rcx
-        movdqu      xmm2,       [rsi+rax*2]
-
-        lea         rsi,        [rsi+rax*2]
-        movdqa      [rdi],      xmm0
-
-        movdqa      [rdi+rcx],  xmm1
-        movdqa      [rdi+rcx*2],xmm2
-
-        movdqu      xmm3,       [rsi+rax]
-        lea         rdi,        [rdi+rcx*2]
-
-        movdqa      [rdi+rcx],  xmm3
-
-    ; begin epilog
-    pop rdi
-    pop rsi
-    UNSHADOW_ARGS
-    pop         rbp
-    ret
diff --git a/vp9/decoder/vp9_decodemv.c b/vp9/decoder/vp9_decodemv.c
index 369505c..3fc62c3 100644
--- a/vp9/decoder/vp9_decodemv.c
+++ b/vp9/decoder/vp9_decodemv.c
@@ -44,8 +44,8 @@
   return (MB_PREDICTION_MODE)treed_read(r, vp9_sb_mv_ref_tree, p);
 }
 
-static int read_segment_id(vp9_reader *r, MACROBLOCKD *xd) {
-  return treed_read(r, vp9_segment_tree, xd->mb_segment_tree_probs);
+static int read_segment_id(vp9_reader *r, const struct segmentation *seg) {
+  return treed_read(r, vp9_segment_tree, seg->tree_probs);
 }
 
 static TX_SIZE read_selected_txfm_size(VP9_COMMON *cm, MACROBLOCKD *xd,
@@ -105,13 +105,13 @@
 
 static int read_intra_segment_id(VP9D_COMP *pbi, int mi_row, int mi_col,
                                  vp9_reader *r) {
-  VP9_COMMON *const cm = &pbi->common;
   MACROBLOCKD *const xd = &pbi->mb;
+  struct segmentation *const seg = &xd->seg;
   const BLOCK_SIZE_TYPE bsize = xd->mode_info_context->mbmi.sb_type;
 
-  if (xd->segmentation_enabled && xd->update_mb_segmentation_map) {
-    const int segment_id = read_segment_id(r, xd);
-    set_segment_id(cm, bsize, mi_row, mi_col, segment_id);
+  if (seg->enabled && seg->update_map) {
+    const int segment_id = read_segment_id(r, seg);
+    set_segment_id(&pbi->common, bsize, mi_row, mi_col, segment_id);
     return segment_id;
   } else {
     return 0;
@@ -121,7 +121,7 @@
 static uint8_t read_skip_coeff(VP9D_COMP *pbi, int segment_id, vp9_reader *r) {
   VP9_COMMON *const cm = &pbi->common;
   MACROBLOCKD *const xd = &pbi->mb;
-  int skip_coeff = vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP);
+  int skip_coeff = vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_SKIP);
   if (!skip_coeff) {
     const uint8_t ctx = vp9_get_pred_context_mbskip(cm, xd);
     skip_coeff = vp9_read(r, vp9_get_pred_prob_mbskip(cm, xd));
@@ -290,8 +290,8 @@
   MACROBLOCKD *const xd = &pbi->mb;
   FRAME_CONTEXT *const fc = &cm->fc;
 
-  if (vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME)) {
-    ref_frame[0] = vp9_get_segdata(xd, segment_id, SEG_LVL_REF_FRAME);
+  if (vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_REF_FRAME)) {
+    ref_frame[0] = vp9_get_segdata(&xd->seg, segment_id, SEG_LVL_REF_FRAME);
     ref_frame[1] = NONE;
   } else {
     const int comp_ctx = vp9_get_pred_context_comp_inter_inter(cm, xd);
@@ -366,26 +366,28 @@
                                  vp9_reader *r) {
   VP9_COMMON *const cm = &pbi->common;
   MACROBLOCKD *const xd = &pbi->mb;
+  struct segmentation *const seg = &xd->seg;
   const BLOCK_SIZE_TYPE bsize = xd->mode_info_context->mbmi.sb_type;
   int pred_segment_id;
   int segment_id;
 
-  if (!xd->segmentation_enabled)
+  if (!seg->enabled)
     return 0;  // Default for disabled segmentation
 
   pred_segment_id = vp9_get_segment_id(cm, cm->last_frame_seg_map,
-                                                   bsize, mi_row, mi_col);
-  if (!xd->update_mb_segmentation_map)
+                                       bsize, mi_row, mi_col);
+  if (!seg->update_map)
     return pred_segment_id;
 
-  if (cm->temporal_update) {
+
+  if (seg->temporal_update) {
     const vp9_prob pred_prob = vp9_get_pred_prob_seg_id(cm, xd);
     const int pred_flag = vp9_read(r, pred_prob);
     vp9_set_pred_flag_seg_id(xd, bsize, pred_flag);
     segment_id = pred_flag ? pred_segment_id
-                           : read_segment_id(r, xd);
+                           : read_segment_id(r, seg);
   } else {
-    segment_id = read_segment_id(r, xd);
+    segment_id = read_segment_id(r, seg);
   }
   set_segment_id(cm, bsize, mi_row, mi_col, segment_id);
   return segment_id;
@@ -455,14 +457,14 @@
   MACROBLOCKD *const xd = &pbi->mb;
 
   MV_REFERENCE_FRAME ref;
-  if (!vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME)) {
+  if (!vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_REF_FRAME)) {
     const int ctx = vp9_get_pred_context_intra_inter(cm, xd);
     ref = (MV_REFERENCE_FRAME)
               vp9_read(r, vp9_get_pred_prob_intra_inter(cm, xd));
     cm->fc.intra_inter_count[ctx][ref != INTRA_FRAME]++;
   } else {
-    ref = (MV_REFERENCE_FRAME)
-              vp9_get_segdata(xd, segment_id, SEG_LVL_REF_FRAME) != INTRA_FRAME;
+    ref = (MV_REFERENCE_FRAME) vp9_get_segdata(&xd->seg, segment_id,
+                                   SEG_LVL_REF_FRAME) != INTRA_FRAME;
   }
   return ref;
 }
@@ -515,7 +517,7 @@
 
     mv_ref_p = cm->fc.inter_mode_probs[mbmi->mb_mode_context[ref0]];
 
-    if (vp9_segfeature_active(xd, mbmi->segment_id, SEG_LVL_SKIP)) {
+    if (vp9_segfeature_active(&xd->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
       mbmi->mode = ZEROMV;
     } else if (bsize >= BLOCK_SIZE_SB8X8) {
       mbmi->mode = read_inter_mode(r, mv_ref_p);
diff --git a/vp9/decoder/vp9_decodframe.c b/vp9/decoder/vp9_decodframe.c
index 37bdad2..48be069 100644
--- a/vp9/decoder/vp9_decodframe.c
+++ b/vp9/decoder/vp9_decodframe.c
@@ -174,7 +174,7 @@
     vp9_reset_sb_tokens_context(xd, bsize);
     return -1;
   } else {
-    if (xd->segmentation_enabled)
+    if (xd->seg.enabled)
       mb_init_dequantizer(&pbi->common, xd);
 
     // TODO(dkovalev) if (!vp9_reader_has_error(r))
@@ -395,55 +395,53 @@
     read_coef_probs_common(fc, TX_32X32, r);
 }
 
-static void setup_segmentation(VP9D_COMP *pbi, struct vp9_read_bit_buffer *rb) {
+static void setup_segmentation(struct segmentation *seg,
+                               struct vp9_read_bit_buffer *rb) {
   int i, j;
 
-  VP9_COMMON *const cm = &pbi->common;
-  MACROBLOCKD *const xd = &pbi->mb;
+  seg->update_map = 0;
+  seg->update_data = 0;
 
-  xd->update_mb_segmentation_map = 0;
-  xd->update_mb_segmentation_data = 0;
-
-  xd->segmentation_enabled = vp9_rb_read_bit(rb);
-  if (!xd->segmentation_enabled)
+  seg->enabled = vp9_rb_read_bit(rb);
+  if (!seg->enabled)
     return;
 
   // Segmentation map update
-  xd->update_mb_segmentation_map = vp9_rb_read_bit(rb);
-  if (xd->update_mb_segmentation_map) {
+  seg->update_map = vp9_rb_read_bit(rb);
+  if (seg->update_map) {
     for (i = 0; i < MB_SEG_TREE_PROBS; i++)
-      xd->mb_segment_tree_probs[i] = vp9_rb_read_bit(rb) ?
-                                         vp9_rb_read_literal(rb, 8) : MAX_PROB;
+      seg->tree_probs[i] = vp9_rb_read_bit(rb) ? vp9_rb_read_literal(rb, 8)
+                                               : MAX_PROB;
 
-    cm->temporal_update = vp9_rb_read_bit(rb);
-    if (cm->temporal_update) {
+    seg->temporal_update = vp9_rb_read_bit(rb);
+    if (seg->temporal_update) {
       for (i = 0; i < PREDICTION_PROBS; i++)
-        cm->segment_pred_probs[i] = vp9_rb_read_bit(rb) ?
-                                        vp9_rb_read_literal(rb, 8) : MAX_PROB;
+        seg->pred_probs[i] = vp9_rb_read_bit(rb) ? vp9_rb_read_literal(rb, 8)
+                                                 : MAX_PROB;
     } else {
       for (i = 0; i < PREDICTION_PROBS; i++)
-        cm->segment_pred_probs[i] = MAX_PROB;
+        seg->pred_probs[i] = MAX_PROB;
     }
   }
 
   // Segmentation data update
-  xd->update_mb_segmentation_data = vp9_rb_read_bit(rb);
-  if (xd->update_mb_segmentation_data) {
-    xd->mb_segment_abs_delta = vp9_rb_read_bit(rb);
+  seg->update_data = vp9_rb_read_bit(rb);
+  if (seg->update_data) {
+    seg->abs_delta = vp9_rb_read_bit(rb);
 
-    vp9_clearall_segfeatures(xd);
+    vp9_clearall_segfeatures(seg);
 
     for (i = 0; i < MAX_MB_SEGMENTS; i++) {
       for (j = 0; j < SEG_LVL_MAX; j++) {
         int data = 0;
         const int feature_enabled = vp9_rb_read_bit(rb);
         if (feature_enabled) {
-          vp9_enable_segfeature(xd, i, j);
+          vp9_enable_segfeature(seg, i, j);
           data = decode_unsigned_max(rb, vp9_seg_feature_data_max(j));
           if (vp9_is_segfeature_signed(j))
             data = vp9_rb_read_bit(rb) ? -data : data;
         }
-        vp9_set_segdata(xd, i, j, data);
+        vp9_set_segdata(seg, i, j, data);
       }
     }
   }
@@ -902,7 +900,7 @@
 
   setup_loopfilter(pbi, rb);
   setup_quantization(pbi, rb);
-  setup_segmentation(pbi, rb);
+  setup_segmentation(&pbi->mb.seg, rb);
 
   setup_tile_info(cm, rb);
 
diff --git a/vp9/decoder/vp9_detokenize.c b/vp9/decoder/vp9_detokenize.c
index 76889c4..3a4fae0 100644
--- a/vp9/decoder/vp9_detokenize.c
+++ b/vp9/decoder/vp9_detokenize.c
@@ -278,8 +278,8 @@
   return c;
 }
 
-static int get_eob(MACROBLOCKD* const xd, int segment_id, int eob_max) {
-  return vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP) ? 0 : eob_max;
+static int get_eob(struct segmentation *seg, int segment_id, int eob_max) {
+  return vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP) ? 0 : eob_max;
 }
 
 struct decode_block_args {
@@ -300,7 +300,7 @@
   struct macroblockd_plane* pd = &xd->plane[plane];
   const int segment_id = xd->mode_info_context->mbmi.segment_id;
   const TX_SIZE ss_tx_size = ss_txfrm_size / 2;
-  const int seg_eob = get_eob(xd, segment_id, 16 << ss_txfrm_size);
+  const int seg_eob = get_eob(&xd->seg, segment_id, 16 << ss_txfrm_size);
   const int off = block >> ss_txfrm_size;
   const int mod = bw - ss_tx_size - pd->subsampling_x;
   const int aoff = (off & ((1 << mod) - 1)) << ss_tx_size;
diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c
index 3a2990c..adeff10 100644
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -216,7 +216,7 @@
 static int write_skip_coeff(const VP9_COMP *cpi, int segment_id, MODE_INFO *m,
                             vp9_writer *w) {
   const MACROBLOCKD *const xd = &cpi->mb.e_mbd;
-  if (vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP)) {
+  if (vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_SKIP)) {
     return 1;
   } else {
     const int skip_coeff = m->mbmi.mb_skip_coeff;
@@ -348,18 +348,18 @@
   *tp = p;
 }
 
-static void write_sb_mv_ref(vp9_writer *w, MB_PREDICTION_MODE m,
+static void write_sb_mv_ref(vp9_writer *w, MB_PREDICTION_MODE mode,
                             const vp9_prob *p) {
-  assert(NEARESTMV <= m && m <= NEWMV);
+  assert(is_inter_mode(mode));
   write_token(w, vp9_sb_mv_ref_tree, p,
-              vp9_sb_mv_ref_encoding_array - NEARESTMV + m);
+              &vp9_sb_mv_ref_encoding_array[mode - NEARESTMV]);
 }
 
 
-static void write_segment_id(vp9_writer *w, const MACROBLOCKD *xd,
+static void write_segment_id(vp9_writer *w, const struct segmentation *seg,
                              int segment_id) {
-  if (xd->segmentation_enabled && xd->update_mb_segmentation_map)
-    treed_write(w, vp9_segment_tree, xd->mb_segment_tree_probs, segment_id, 3);
+  if (seg->enabled && seg->update_map)
+    treed_write(w, vp9_segment_tree, seg->tree_probs, segment_id, 3);
 }
 
 // This function encodes the reference frame
@@ -369,7 +369,7 @@
   MACROBLOCKD *const xd = &x->e_mbd;
   MB_MODE_INFO *mi = &xd->mode_info_context->mbmi;
   const int segment_id = mi->segment_id;
-  int seg_ref_active = vp9_segfeature_active(xd, segment_id,
+  int seg_ref_active = vp9_segfeature_active(&xd->seg, segment_id,
                                              SEG_LVL_REF_FRAME);
   // If segment level coding of this signal is disabled...
   // or the segment allows multiple reference frame options
@@ -396,7 +396,7 @@
     }
   } else {
     assert(mi->ref_frame[1] <= INTRA_FRAME);
-    assert(vp9_get_segdata(xd, segment_id, SEG_LVL_REF_FRAME) ==
+    assert(vp9_get_segdata(&xd->seg, segment_id, SEG_LVL_REF_FRAME) ==
            mi->ref_frame[0]);
   }
 
@@ -410,6 +410,7 @@
   const nmv_context *nmvc = &pc->fc.nmvc;
   MACROBLOCK *const x = &cpi->mb;
   MACROBLOCKD *const xd = &x->e_mbd;
+  struct segmentation *seg = &xd->seg;
   MB_MODE_INFO *const mi = &m->mbmi;
   const MV_REFERENCE_FRAME rf = mi->ref_frame[0];
   const MB_PREDICTION_MODE mode = mi->mode;
@@ -423,33 +424,27 @@
   active_section = 9;
 #endif
 
-  if (cpi->mb.e_mbd.update_mb_segmentation_map) {
-    // Is temporal coding of the segment map enabled
-    if (pc->temporal_update) {
+  if (seg->update_map) {
+    if (seg->temporal_update) {
       unsigned char prediction_flag = vp9_get_pred_flag_seg_id(xd);
       vp9_prob pred_prob = vp9_get_pred_prob_seg_id(pc, xd);
-
-      // Code the segment id prediction flag for this mb
       vp9_write(bc, prediction_flag, pred_prob);
-
-      // If the mb segment id wasn't predicted code explicitly
       if (!prediction_flag)
-        write_segment_id(bc, xd, mi->segment_id);
+        write_segment_id(bc, seg, mi->segment_id);
     } else {
-      // Normal unpredicted coding
-        write_segment_id(bc, xd, mi->segment_id);
+      write_segment_id(bc, seg, mi->segment_id);
     }
   }
 
   skip_coeff = write_skip_coeff(cpi, segment_id, m, bc);
 
-  if (!vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME))
+  if (!vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME))
     vp9_write(bc, rf != INTRA_FRAME,
               vp9_get_pred_prob_intra_inter(pc, xd));
 
   if (mi->sb_type >= BLOCK_SIZE_SB8X8 && pc->txfm_mode == TX_MODE_SELECT &&
       !(rf != INTRA_FRAME &&
-        (skip_coeff || vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP)))) {
+        (skip_coeff || vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP)))) {
     write_selected_txfm_size(cpi, mi->txfm_size, mi->sb_type, bc);
   }
 
@@ -484,7 +479,7 @@
 #endif
 
     // If segment skip is not enabled code the mode.
-    if (!vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP)) {
+    if (!vp9_segfeature_active(seg, segment_id, SEG_LVL_SKIP)) {
       if (mi->sb_type >= BLOCK_SIZE_SB8X8) {
         write_sb_mv_ref(bc, mode, mv_ref_p);
         vp9_accum_mv_refs(&cpi->common, mode, mi->mb_mode_context[rf]);
@@ -554,8 +549,8 @@
   const int mis = c->mode_info_stride;
   const int segment_id = m->mbmi.segment_id;
 
-  if (xd->update_mb_segmentation_map)
-    write_segment_id(bc, xd, m->mbmi.segment_id);
+  if (xd->seg.update_map)
+    write_segment_id(bc, &xd->seg, m->mbmi.segment_id);
 
   write_skip_coeff(cpi, segment_id, m, bc);
 
@@ -1002,23 +997,23 @@
 
 
 static void encode_segmentation(VP9_COMP *cpi,
-                               struct vp9_write_bit_buffer *wb) {
+                                struct vp9_write_bit_buffer *wb) {
   int i, j;
-  VP9_COMMON *const cm = &cpi->common;
-  MACROBLOCKD *const xd = &cpi->mb.e_mbd;
 
-  vp9_wb_write_bit(wb, xd->segmentation_enabled);
-  if (!xd->segmentation_enabled)
+  struct segmentation *seg = &cpi->mb.e_mbd.seg;
+
+  vp9_wb_write_bit(wb, seg->enabled);
+  if (!seg->enabled)
     return;
 
   // Segmentation map
-  vp9_wb_write_bit(wb, xd->update_mb_segmentation_map);
-  if (xd->update_mb_segmentation_map) {
+  vp9_wb_write_bit(wb, seg->update_map);
+  if (seg->update_map) {
     // Select the coding strategy (temporal or spatial)
     vp9_choose_segmap_coding_method(cpi);
     // Write out probabilities used to decode unpredicted  macro-block segments
     for (i = 0; i < MB_SEG_TREE_PROBS; i++) {
-      const int prob = xd->mb_segment_tree_probs[i];
+      const int prob = seg->tree_probs[i];
       const int update = prob != MAX_PROB;
       vp9_wb_write_bit(wb, update);
       if (update)
@@ -1026,10 +1021,10 @@
     }
 
     // Write out the chosen coding method.
-    vp9_wb_write_bit(wb, cm->temporal_update);
-    if (cm->temporal_update) {
+    vp9_wb_write_bit(wb, seg->temporal_update);
+    if (seg->temporal_update) {
       for (i = 0; i < PREDICTION_PROBS; i++) {
-        const int prob = cm->segment_pred_probs[i];
+        const int prob = seg->pred_probs[i];
         const int update = prob != MAX_PROB;
         vp9_wb_write_bit(wb, update);
         if (update)
@@ -1039,16 +1034,16 @@
   }
 
   // Segmentation data
-  vp9_wb_write_bit(wb, xd->update_mb_segmentation_data);
-  if (xd->update_mb_segmentation_data) {
-    vp9_wb_write_bit(wb, xd->mb_segment_abs_delta);
+  vp9_wb_write_bit(wb, seg->update_data);
+  if (seg->update_data) {
+    vp9_wb_write_bit(wb, seg->abs_delta);
 
     for (i = 0; i < MAX_MB_SEGMENTS; i++) {
       for (j = 0; j < SEG_LVL_MAX; j++) {
-        const int active = vp9_segfeature_active(xd, i, j);
+        const int active = vp9_segfeature_active(seg, i, j);
         vp9_wb_write_bit(wb, active);
         if (active) {
-          const int data = vp9_get_segdata(xd, i, j);
+          const int data = vp9_get_segdata(seg, i, j);
           const int data_max = vp9_seg_feature_data_max(j);
 
           if (vp9_is_segfeature_signed(j)) {
@@ -1385,27 +1380,112 @@
   write_tile_info(cm, wb);
 }
 
-void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, unsigned long *size) {
-  int i, bytes_packed;
-  VP9_COMMON *const pc = &cpi->common;
-  vp9_writer header_bc;
+static size_t write_compressed_header(VP9_COMP *cpi, uint8_t *data) {
+  VP9_COMMON *const cm = &cpi->common;
   MACROBLOCKD *const xd = &cpi->mb.e_mbd;
+  FRAME_CONTEXT *const fc = &cm->fc;
+  vp9_writer header_bc;
 
-  uint8_t *cx_data = dest;
-  struct vp9_write_bit_buffer wb = {dest, 0};
-  struct vp9_write_bit_buffer first_partition_size_wb;
+  vp9_start_encode(&header_bc, data);
+
+  if (xd->lossless)
+    cm->txfm_mode = ONLY_4X4;
+  else
+    encode_txfm_probs(cpi, &header_bc);
+
+  update_coef_probs(cpi, &header_bc);
+
+#ifdef ENTROPY_STATS
+  active_section = 2;
+#endif
+
+  vp9_update_skip_probs(cpi, &header_bc);
+
+  if (cm->frame_type != KEY_FRAME) {
+    int i;
+#ifdef ENTROPY_STATS
+    active_section = 1;
+#endif
+
+    update_inter_mode_probs(cm, &header_bc);
+    vp9_zero(fc->inter_mode_counts);
+
+    if (cm->mcomp_filter_type == SWITCHABLE)
+      update_switchable_interp_probs(cpi, &header_bc);
+
+    for (i = 0; i < INTRA_INTER_CONTEXTS; i++)
+      vp9_cond_prob_diff_update(&header_bc, &fc->intra_inter_prob[i],
+                                VP9_MODE_UPDATE_PROB,
+                                cpi->intra_inter_count[i]);
+
+    if (cm->allow_comp_inter_inter) {
+      const int comp_pred_mode = cpi->common.comp_pred_mode;
+      const int use_compound_pred = comp_pred_mode != SINGLE_PREDICTION_ONLY;
+      const int use_hybrid_pred = comp_pred_mode == HYBRID_PREDICTION;
+
+      vp9_write_bit(&header_bc, use_compound_pred);
+      if (use_compound_pred) {
+        vp9_write_bit(&header_bc, use_hybrid_pred);
+        if (use_hybrid_pred)
+          for (i = 0; i < COMP_INTER_CONTEXTS; i++)
+            vp9_cond_prob_diff_update(&header_bc, &fc->comp_inter_prob[i],
+                                      VP9_MODE_UPDATE_PROB,
+                                      cpi->comp_inter_count[i]);
+      }
+    }
+
+    if (cm->comp_pred_mode != COMP_PREDICTION_ONLY) {
+      for (i = 0; i < REF_CONTEXTS; i++) {
+        vp9_cond_prob_diff_update(&header_bc, &fc->single_ref_prob[i][0],
+                                  VP9_MODE_UPDATE_PROB,
+                                  cpi->single_ref_count[i][0]);
+        vp9_cond_prob_diff_update(&header_bc, &fc->single_ref_prob[i][1],
+                                  VP9_MODE_UPDATE_PROB,
+                                  cpi->single_ref_count[i][1]);
+      }
+    }
+
+    if (cm->comp_pred_mode != SINGLE_PREDICTION_ONLY)
+      for (i = 0; i < REF_CONTEXTS; i++)
+        vp9_cond_prob_diff_update(&header_bc, &fc->comp_ref_prob[i],
+                                  VP9_MODE_UPDATE_PROB,
+                                  cpi->comp_ref_count[i]);
+
+    update_mbintra_mode_probs(cpi, &header_bc);
+
+    for (i = 0; i < NUM_PARTITION_CONTEXTS; ++i) {
+      vp9_prob pnew[PARTITION_TYPES - 1];
+      unsigned int bct[PARTITION_TYPES - 1][2];
+      update_mode(&header_bc, PARTITION_TYPES, vp9_partition_encodings,
+                  vp9_partition_tree, pnew,
+                  fc->partition_prob[cm->frame_type][i], bct,
+                  (unsigned int *)cpi->partition_count[i]);
+    }
+
+    vp9_write_nmv_probs(cpi, xd->allow_high_precision_mv, &header_bc);
+  }
+
+  vp9_stop_encode(&header_bc);
+  assert(header_bc.pos <= 0xffff);
+
+  return header_bc.pos;
+}
+
+void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, unsigned long *size) {
+  FRAME_CONTEXT *const fc = &cpi->common.fc;
+  uint8_t *data = dest;
+  size_t first_part_size;
+  struct vp9_write_bit_buffer wb = {data, 0};
+  struct vp9_write_bit_buffer saved_wb;
 
   write_uncompressed_header(cpi, &wb);
-  first_partition_size_wb = wb;
+  saved_wb = wb;
   vp9_wb_write_literal(&wb, 0, 16);  // don't know in advance first part. size
 
-  bytes_packed = vp9_rb_bytes_written(&wb);
-  cx_data += bytes_packed;
+  data += vp9_rb_bytes_written(&wb);
 
   vp9_compute_update_table();
 
-  vp9_start_encode(&header_bc, cx_data);
-
 #ifdef ENTROPY_STATS
   if (pc->frame_type == INTER_FRAME)
     active_section = 0;
@@ -1415,110 +1495,29 @@
 
   vp9_clear_system_state();  // __asm emms;
 
-  vp9_copy(pc->fc.pre_coef_probs, pc->fc.coef_probs);
-  vp9_copy(pc->fc.pre_y_mode_prob, pc->fc.y_mode_prob);
-  vp9_copy(pc->fc.pre_uv_mode_prob, pc->fc.uv_mode_prob);
-  vp9_copy(pc->fc.pre_partition_prob, pc->fc.partition_prob[INTER_FRAME]);
-  pc->fc.pre_nmvc = pc->fc.nmvc;
-  vp9_copy(pc->fc.pre_switchable_interp_prob, pc->fc.switchable_interp_prob);
-  vp9_copy(pc->fc.pre_inter_mode_probs, pc->fc.inter_mode_probs);
-  vp9_copy(pc->fc.pre_intra_inter_prob, pc->fc.intra_inter_prob);
-  vp9_copy(pc->fc.pre_comp_inter_prob, pc->fc.comp_inter_prob);
-  vp9_copy(pc->fc.pre_comp_ref_prob, pc->fc.comp_ref_prob);
-  vp9_copy(pc->fc.pre_single_ref_prob, pc->fc.single_ref_prob);
-  vp9_copy(pc->fc.pre_tx_probs_8x8p, pc->fc.tx_probs_8x8p);
-  vp9_copy(pc->fc.pre_tx_probs_16x16p, pc->fc.tx_probs_16x16p);
-  vp9_copy(pc->fc.pre_tx_probs_32x32p, pc->fc.tx_probs_32x32p);
-  vp9_copy(pc->fc.pre_mbskip_probs, pc->fc.mbskip_probs);
+  vp9_copy(fc->pre_coef_probs, fc->coef_probs);
+  vp9_copy(fc->pre_y_mode_prob, fc->y_mode_prob);
+  vp9_copy(fc->pre_uv_mode_prob, fc->uv_mode_prob);
+  vp9_copy(fc->pre_partition_prob, fc->partition_prob[INTER_FRAME]);
+  fc->pre_nmvc = fc->nmvc;
+  vp9_copy(fc->pre_switchable_interp_prob, fc->switchable_interp_prob);
+  vp9_copy(fc->pre_inter_mode_probs, fc->inter_mode_probs);
+  vp9_copy(fc->pre_intra_inter_prob, fc->intra_inter_prob);
+  vp9_copy(fc->pre_comp_inter_prob, fc->comp_inter_prob);
+  vp9_copy(fc->pre_comp_ref_prob, fc->comp_ref_prob);
+  vp9_copy(fc->pre_single_ref_prob, fc->single_ref_prob);
+  vp9_copy(fc->pre_tx_probs_8x8p, fc->tx_probs_8x8p);
+  vp9_copy(fc->pre_tx_probs_16x16p, fc->tx_probs_16x16p);
+  vp9_copy(fc->pre_tx_probs_32x32p, fc->tx_probs_32x32p);
+  vp9_copy(fc->pre_mbskip_probs, fc->mbskip_probs);
 
-  if (xd->lossless) {
-    pc->txfm_mode = ONLY_4X4;
-  } else {
-    encode_txfm_probs(cpi, &header_bc);
-  }
+  first_part_size = write_compressed_header(cpi, data);
+  data += first_part_size;
+  vp9_wb_write_literal(&saved_wb, first_part_size, 16);
 
-  update_coef_probs(cpi, &header_bc);
+  data += encode_tiles(cpi, data);
 
-#ifdef ENTROPY_STATS
-  active_section = 2;
-#endif
-
-  vp9_update_skip_probs(cpi, &header_bc);
-
-  if (pc->frame_type != KEY_FRAME) {
-#ifdef ENTROPY_STATS
-    active_section = 1;
-#endif
-
-    update_inter_mode_probs(pc, &header_bc);
-    vp9_zero(cpi->common.fc.inter_mode_counts);
-
-    if (pc->mcomp_filter_type == SWITCHABLE)
-      update_switchable_interp_probs(cpi, &header_bc);
-
-    for (i = 0; i < INTRA_INTER_CONTEXTS; i++)
-      vp9_cond_prob_diff_update(&header_bc, &pc->fc.intra_inter_prob[i],
-                                VP9_MODE_UPDATE_PROB,
-                                cpi->intra_inter_count[i]);
-
-    if (pc->allow_comp_inter_inter) {
-      const int comp_pred_mode = cpi->common.comp_pred_mode;
-      const int use_compound_pred = (comp_pred_mode != SINGLE_PREDICTION_ONLY);
-      const int use_hybrid_pred = (comp_pred_mode == HYBRID_PREDICTION);
-
-      vp9_write_bit(&header_bc, use_compound_pred);
-      if (use_compound_pred) {
-        vp9_write_bit(&header_bc, use_hybrid_pred);
-        if (use_hybrid_pred) {
-          for (i = 0; i < COMP_INTER_CONTEXTS; i++)
-            vp9_cond_prob_diff_update(&header_bc, &pc->fc.comp_inter_prob[i],
-                                      VP9_MODE_UPDATE_PROB,
-                                      cpi->comp_inter_count[i]);
-        }
-      }
-    }
-
-    if (pc->comp_pred_mode != COMP_PREDICTION_ONLY) {
-      for (i = 0; i < REF_CONTEXTS; i++) {
-        vp9_cond_prob_diff_update(&header_bc, &pc->fc.single_ref_prob[i][0],
-                                  VP9_MODE_UPDATE_PROB,
-                                  cpi->single_ref_count[i][0]);
-        vp9_cond_prob_diff_update(&header_bc, &pc->fc.single_ref_prob[i][1],
-                                  VP9_MODE_UPDATE_PROB,
-                                  cpi->single_ref_count[i][1]);
-      }
-    }
-
-    if (pc->comp_pred_mode != SINGLE_PREDICTION_ONLY) {
-      for (i = 0; i < REF_CONTEXTS; i++)
-        vp9_cond_prob_diff_update(&header_bc, &pc->fc.comp_ref_prob[i],
-                                  VP9_MODE_UPDATE_PROB,
-                                  cpi->comp_ref_count[i]);
-    }
-
-    update_mbintra_mode_probs(cpi, &header_bc);
-
-    for (i = 0; i < NUM_PARTITION_CONTEXTS; ++i) {
-      vp9_prob Pnew[PARTITION_TYPES - 1];
-      unsigned int bct[PARTITION_TYPES - 1][2];
-      update_mode(&header_bc, PARTITION_TYPES, vp9_partition_encodings,
-                  vp9_partition_tree, Pnew,
-                  pc->fc.partition_prob[pc->frame_type][i], bct,
-                  (unsigned int *)cpi->partition_count[i]);
-    }
-
-    vp9_write_nmv_probs(cpi, xd->allow_high_precision_mv, &header_bc);
-  }
-
-
-  vp9_stop_encode(&header_bc);
-
-
-  // first partition size
-  assert(header_bc.pos <= 0xffff);
-  vp9_wb_write_literal(&first_partition_size_wb, header_bc.pos, 16);
-  *size = bytes_packed + header_bc.pos;
-  *size += encode_tiles(cpi, cx_data + header_bc.pos);
+  *size = data - dest;
 }
 
 #ifdef ENTROPY_STATS
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index adaf667..a3e116b 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -360,7 +360,7 @@
   if (!output_enabled)
     return;
 
-  if (!vp9_segfeature_active(xd, mbmi->segment_id, SEG_LVL_SKIP)) {
+  if (!vp9_segfeature_active(&xd->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
     for (i = 0; i < NB_TXFM_MODES; i++) {
       cpi->rd_tx_select_diff[i] += ctx->txfm_rd_diff[i];
     }
@@ -512,16 +512,16 @@
   x->rdmult = cpi->RDMULT;
 
   /* segment ID */
-  if (xd->segmentation_enabled) {
-    uint8_t *map = xd->update_mb_segmentation_map ? cpi->segmentation_map
-                                                  : cm->last_frame_seg_map;
+  if (xd->seg.enabled) {
+    uint8_t *map = xd->seg.update_map ? cpi->segmentation_map
+                                      : cm->last_frame_seg_map;
     mbmi->segment_id = vp9_get_segment_id(cm, map, bsize, mi_row, mi_col);
 
     vp9_mb_init_quantizer(cpi, x);
 
-    if (xd->segmentation_enabled && cpi->seg0_cnt > 0
-        && !vp9_segfeature_active(xd, 0, SEG_LVL_REF_FRAME)
-        && vp9_segfeature_active(xd, 1, SEG_LVL_REF_FRAME)) {
+    if (xd->seg.enabled && cpi->seg0_cnt > 0
+        && !vp9_segfeature_active(&xd->seg, 0, SEG_LVL_REF_FRAME)
+        && vp9_segfeature_active(&xd->seg, 1, SEG_LVL_REF_FRAME)) {
       cpi->seg0_progress = (cpi->seg0_idx << 16) / cpi->seg0_cnt;
     } else {
       const int y = mb_row & ~3;
@@ -541,11 +541,11 @@
 }
 
 static void pick_sb_modes(VP9_COMP *cpi, int mi_row, int mi_col,
-                          TOKENEXTRA **tp, int *totalrate, int64_t *totaldist,
+                          int *totalrate, int64_t *totaldist,
                           BLOCK_SIZE_TYPE bsize, PICK_MODE_CONTEXT *ctx) {
-  VP9_COMMON * const cm = &cpi->common;
-  MACROBLOCK * const x = &cpi->mb;
-  MACROBLOCKD * const xd = &x->e_mbd;
+  VP9_COMMON *const cm = &cpi->common;
+  MACROBLOCK *const x = &cpi->mb;
+  MACROBLOCKD *const xd = &x->e_mbd;
 
   x->rd_search = 1;
 
@@ -558,14 +558,13 @@
   if (cpi->oxcf.tuning == VP8_TUNE_SSIM)
     vp9_activity_masking(cpi, x);
 
-  /* Find best coding mode & reconstruct the MB so it is available
-   * as a predictor for MBs that follow in the SB */
-  if (cm->frame_type == KEY_FRAME) {
+  // Find best coding mode & reconstruct the MB so it is available
+  // as a predictor for MBs that follow in the SB
+  if (cm->frame_type == KEY_FRAME)
     vp9_rd_pick_intra_mode_sb(cpi, x, totalrate, totaldist, bsize, ctx);
-  } else {
+  else
     vp9_rd_pick_inter_mode_sb(cpi, x, mi_row, mi_col, totalrate, totaldist,
                               bsize, ctx);
-  }
 }
 
 static void update_stats(VP9_COMP *cpi, int mi_row, int mi_col) {
@@ -576,10 +575,8 @@
   MB_MODE_INFO * const mbmi = &mi->mbmi;
 
   if (cm->frame_type != KEY_FRAME) {
-    int segment_id, seg_ref_active;
-
-    segment_id = mbmi->segment_id;
-    seg_ref_active = vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME);
+    const int seg_ref_active = vp9_segfeature_active(&xd->seg, mbmi->segment_id,
+                                                     SEG_LVL_REF_FRAME);
 
     if (!seg_ref_active)
       cpi->intra_inter_count[vp9_get_pred_context_intra_inter(cm, xd)][mbmi
@@ -1232,7 +1229,7 @@
         mi_row + (ms >> 1) < cm->mi_rows &&
         mi_col + (ms >> 1) < cm->mi_cols) {
       *(get_sb_partitioning(x, bsize)) = bsize;
-      pick_sb_modes(cpi, mi_row, mi_col, tp, &none_rate, &none_dist, bsize,
+      pick_sb_modes(cpi, mi_row, mi_col, &none_rate, &none_dist, bsize,
                     get_block_context(x, bsize));
 
       set_partition_seg_context(cm, xd, mi_row, mi_col);
@@ -1247,7 +1244,7 @@
 
   switch (partition) {
     case PARTITION_NONE:
-      pick_sb_modes(cpi, mi_row, mi_col, tp, &last_part_rate, &last_part_dist,
+      pick_sb_modes(cpi, mi_row, mi_col, &last_part_rate, &last_part_dist,
                     bsize, get_block_context(x, bsize));
       set_partition_seg_context(cm, xd, mi_row, mi_col);
       pl = partition_plane_context(xd, bsize);
@@ -1255,7 +1252,7 @@
       break;
     case PARTITION_HORZ:
       *(get_sb_index(xd, subsize)) = 0;
-      pick_sb_modes(cpi, mi_row, mi_col, tp, &last_part_rate, &last_part_dist,
+      pick_sb_modes(cpi, mi_row, mi_col, &last_part_rate, &last_part_dist,
                     subsize, get_block_context(x, subsize));
       if (bsize >= BLOCK_SIZE_SB8X8 && mi_row + (mh >> 1) < cm->mi_rows) {
         int rt = 0;
@@ -1263,7 +1260,7 @@
         update_state(cpi, get_block_context(x, subsize), subsize, 0);
         encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize);
         *(get_sb_index(xd, subsize)) = 1;
-        pick_sb_modes(cpi, mi_row + (ms >> 1), mi_col, tp, &rt, &dt, subsize,
+        pick_sb_modes(cpi, mi_row + (ms >> 1), mi_col, &rt, &dt, subsize,
                       get_block_context(x, subsize));
         last_part_rate += rt;
         last_part_dist += dt;
@@ -1274,7 +1271,7 @@
       break;
     case PARTITION_VERT:
       *(get_sb_index(xd, subsize)) = 0;
-      pick_sb_modes(cpi, mi_row, mi_col, tp, &last_part_rate, &last_part_dist,
+      pick_sb_modes(cpi, mi_row, mi_col, &last_part_rate, &last_part_dist,
                     subsize, get_block_context(x, subsize));
       if (bsize >= BLOCK_SIZE_SB8X8 && mi_col + (ms >> 1) < cm->mi_cols) {
         int rt = 0;
@@ -1282,7 +1279,7 @@
         update_state(cpi, get_block_context(x, subsize), subsize, 0);
         encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize);
         *(get_sb_index(xd, subsize)) = 1;
-        pick_sb_modes(cpi, mi_row, mi_col + (ms >> 1), tp, &rt, &dt, subsize,
+        pick_sb_modes(cpi, mi_row, mi_col + (ms >> 1), &rt, &dt, subsize,
                       get_block_context(x, subsize));
         last_part_rate += rt;
         last_part_dist += dt;
@@ -1347,7 +1344,7 @@
 
       save_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
 
-      pick_sb_modes(cpi, mi_row + y_idx, mi_col + x_idx, tp, &rt, &dt,
+      pick_sb_modes(cpi, mi_row + y_idx, mi_col + x_idx, &rt, &dt,
                     split_subsize, get_block_context(x, split_subsize));
 
       restore_context(cpi, mi_row, mi_col, a, l, sa, sl, bsize);
@@ -1478,7 +1475,7 @@
         (mi_col + (ms >> 1) < cm->mi_cols)) {
       int r;
       int64_t d;
-      pick_sb_modes(cpi, mi_row, mi_col, tp, &r, &d, bsize,
+      pick_sb_modes(cpi, mi_row, mi_col, &r, &d, bsize,
                     get_block_context(x, bsize));
       if (bsize >= BLOCK_SIZE_SB8X8) {
         set_partition_seg_context(cm, xd, mi_row, mi_col);
@@ -1503,7 +1500,7 @@
         int64_t d2, d = 0;
         subsize = get_subsize(bsize, PARTITION_HORZ);
         *(get_sb_index(xd, subsize)) = 0;
-        pick_sb_modes(cpi, mi_row, mi_col, tp, &r2, &d2, subsize,
+        pick_sb_modes(cpi, mi_row, mi_col, &r2, &d2, subsize,
                       get_block_context(x, subsize));
 
         if (mi_row + (ms >> 1) < cm->mi_rows) {
@@ -1511,7 +1508,7 @@
           encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize);
 
           *(get_sb_index(xd, subsize)) = 1;
-          pick_sb_modes(cpi, mi_row + (ms >> 1), mi_col, tp, &r, &d, subsize,
+          pick_sb_modes(cpi, mi_row + (ms >> 1), mi_col, &r, &d, subsize,
                         get_block_context(x, subsize));
           r2 += r;
           d2 += d;
@@ -1535,7 +1532,7 @@
         int64_t d2;
         subsize = get_subsize(bsize, PARTITION_VERT);
         *(get_sb_index(xd, subsize)) = 0;
-        pick_sb_modes(cpi, mi_row, mi_col, tp, &r2, &d2, subsize,
+        pick_sb_modes(cpi, mi_row, mi_col, &r2, &d2, subsize,
                       get_block_context(x, subsize));
         if (mi_col + (ms >> 1) < cm->mi_cols) {
           int r = 0;
@@ -1544,7 +1541,7 @@
           encode_superblock(cpi, tp, 0, mi_row, mi_col, subsize);
 
           *(get_sb_index(xd, subsize)) = 1;
-          pick_sb_modes(cpi, mi_row, mi_col + (ms >> 1), tp, &r, &d, subsize,
+          pick_sb_modes(cpi, mi_row, mi_col + (ms >> 1), &r, &d, subsize,
                         get_block_context(x, subsize));
           r2 += r;
           d2 += d;
@@ -1603,7 +1600,7 @@
   if ((mi_row + (ms >> 1) < cm->mi_rows) &&
       (mi_col + (ms >> 1) < cm->mi_cols)) {
     cpi->set_ref_frame_mask = 1;
-    pick_sb_modes(cpi, mi_row, mi_col, tp, &r, &d, BLOCK_SIZE_SB64X64,
+    pick_sb_modes(cpi, mi_row, mi_col, &r, &d, BLOCK_SIZE_SB64X64,
                   get_block_context(x, BLOCK_SIZE_SB64X64));
     set_partition_seg_context(cm, xd, mi_row, mi_col);
     pl = partition_plane_context(xd, BLOCK_SIZE_SB64X64);
@@ -1886,7 +1883,7 @@
   MACROBLOCKD *xd = &cpi->mb.e_mbd;
   int ref_flags = cpi->ref_frame_flags;
 
-  if (vp9_segfeature_active(xd, 1, SEG_LVL_REF_FRAME)) {
+  if (vp9_segfeature_active(&xd->seg, 1, SEG_LVL_REF_FRAME)) {
     return 0;
   } else {
     return (!!(ref_flags & VP9_GOLD_FLAG) + !!(ref_flags & VP9_LAST_FLAG)
@@ -1933,9 +1930,8 @@
     const int xmbs = MIN(bw, cm->mi_cols - mi_col);
 
     xd->mode_info_context = mi;
-    assert(
-        vp9_segfeature_active(xd, mbmi->segment_id, SEG_LVL_SKIP) ||
-        get_skip_flag(mi, mis, ymbs, xmbs));
+    assert(vp9_segfeature_active(&xd->seg, mbmi->segment_id, SEG_LVL_SKIP) ||
+           get_skip_flag(mi, mis, ymbs, xmbs));
     set_txfm_flag(mi, mis, ymbs, xmbs, txfm_max);
   }
 }
@@ -2371,10 +2367,11 @@
   vp9_set_pred_flag_mbskip(xd, bsize, mi->mbmi.mb_skip_coeff);
 
   if (output_enabled) {
-    if (cm->txfm_mode == TX_MODE_SELECT && mbmi->sb_type >= BLOCK_SIZE_SB8X8
-        && !(mbmi->ref_frame[0] != INTRA_FRAME
-            && (mbmi->mb_skip_coeff
-                || vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP)))) {
+    if (cm->txfm_mode == TX_MODE_SELECT &&
+        mbmi->sb_type >= BLOCK_SIZE_SB8X8  &&
+        !(mbmi->ref_frame[0] != INTRA_FRAME &&
+            (mbmi->mb_skip_coeff ||
+             vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_SKIP)))) {
       const int context = vp9_get_pred_context_tx_size(cm, xd);
       if (bsize >= BLOCK_SIZE_SB32X32) {
         cm->fc.tx_count_32x32p[context][mbmi->txfm_size]++;
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index 67d0c4c..486686a 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -219,13 +219,13 @@
   MACROBLOCKD *xd = &cpi->mb.e_mbd;
 
   // Set up default state for MB feature flags
-  xd->segmentation_enabled = 0;
+  xd->seg.enabled = 0;
 
-  xd->update_mb_segmentation_map = 0;
-  xd->update_mb_segmentation_data = 0;
-  vpx_memset(xd->mb_segment_tree_probs, 255, sizeof(xd->mb_segment_tree_probs));
+  xd->seg.update_map = 0;
+  xd->seg.update_data = 0;
+  vpx_memset(xd->seg.tree_probs, 255, sizeof(xd->seg.tree_probs));
 
-  vp9_clearall_segfeatures(xd);
+  vp9_clearall_segfeatures(&xd->seg);
 
   xd->mode_ref_lf_delta_enabled = 0;
   xd->mode_ref_lf_delta_update = 0;
@@ -305,26 +305,26 @@
   if (cm->frame_type == KEY_FRAME) {
     // Clear down the global segmentation map
     vpx_memset(cpi->segmentation_map, 0, cm->mi_rows * cm->mi_cols);
-    xd->update_mb_segmentation_map = 0;
-    xd->update_mb_segmentation_data = 0;
+    xd->seg.update_map = 0;
+    xd->seg.update_data = 0;
     cpi->static_mb_pct = 0;
 
     // Disable segmentation
     vp9_disable_segmentation((VP9_PTR)cpi);
 
     // Clear down the segment features.
-    vp9_clearall_segfeatures(xd);
+    vp9_clearall_segfeatures(&xd->seg);
   } else if (cpi->refresh_alt_ref_frame) {
     // If this is an alt ref frame
     // Clear down the global segmentation map
     vpx_memset(cpi->segmentation_map, 0, cm->mi_rows * cm->mi_cols);
-    xd->update_mb_segmentation_map = 0;
-    xd->update_mb_segmentation_data = 0;
+    xd->seg.update_map = 0;
+    xd->seg.update_data = 0;
     cpi->static_mb_pct = 0;
 
     // Disable segmentation and individual segment features by default
     vp9_disable_segmentation((VP9_PTR)cpi);
-    vp9_clearall_segfeatures(xd);
+    vp9_clearall_segfeatures(&xd->seg);
 
     // Scan frames from current to arf frame.
     // This function re-enables segmentation if appropriate.
@@ -332,45 +332,45 @@
 
     // If segmentation was enabled set those features needed for the
     // arf itself.
-    if (xd->segmentation_enabled) {
-      xd->update_mb_segmentation_map = 1;
-      xd->update_mb_segmentation_data = 1;
+    if (xd->seg.enabled) {
+      xd->seg.update_map = 1;
+      xd->seg.update_data = 1;
 
       qi_delta = compute_qdelta(cpi, cpi->avg_q, (cpi->avg_q * 0.875));
-      vp9_set_segdata(xd, 1, SEG_LVL_ALT_Q, (qi_delta - 2));
-      vp9_set_segdata(xd, 1, SEG_LVL_ALT_LF, -2);
+      vp9_set_segdata(&xd->seg, 1, SEG_LVL_ALT_Q, (qi_delta - 2));
+      vp9_set_segdata(&xd->seg, 1, SEG_LVL_ALT_LF, -2);
 
-      vp9_enable_segfeature(xd, 1, SEG_LVL_ALT_Q);
-      vp9_enable_segfeature(xd, 1, SEG_LVL_ALT_LF);
+      vp9_enable_segfeature(&xd->seg, 1, SEG_LVL_ALT_Q);
+      vp9_enable_segfeature(&xd->seg, 1, SEG_LVL_ALT_LF);
 
       // Where relevant assume segment data is delta data
-      xd->mb_segment_abs_delta = SEGMENT_DELTADATA;
+      xd->seg.abs_delta = SEGMENT_DELTADATA;
 
     }
-  } else if (xd->segmentation_enabled) {
+  } else if (xd->seg.enabled) {
     // All other frames if segmentation has been enabled
 
     // First normal frame in a valid gf or alt ref group
     if (cpi->common.frames_since_golden == 0) {
       // Set up segment features for normal frames in an arf group
       if (cpi->source_alt_ref_active) {
-        xd->update_mb_segmentation_map = 0;
-        xd->update_mb_segmentation_data = 1;
-        xd->mb_segment_abs_delta = SEGMENT_DELTADATA;
+        xd->seg.update_map = 0;
+        xd->seg.update_data = 1;
+        xd->seg.abs_delta = SEGMENT_DELTADATA;
 
         qi_delta = compute_qdelta(cpi, cpi->avg_q,
                                   (cpi->avg_q * 1.125));
-        vp9_set_segdata(xd, 1, SEG_LVL_ALT_Q, (qi_delta + 2));
-        vp9_enable_segfeature(xd, 1, SEG_LVL_ALT_Q);
+        vp9_set_segdata(&xd->seg, 1, SEG_LVL_ALT_Q, (qi_delta + 2));
+        vp9_enable_segfeature(&xd->seg, 1, SEG_LVL_ALT_Q);
 
-        vp9_set_segdata(xd, 1, SEG_LVL_ALT_LF, -2);
-        vp9_enable_segfeature(xd, 1, SEG_LVL_ALT_LF);
+        vp9_set_segdata(&xd->seg, 1, SEG_LVL_ALT_LF, -2);
+        vp9_enable_segfeature(&xd->seg, 1, SEG_LVL_ALT_LF);
 
         // Segment coding disabled for compred testing
         if (high_q || (cpi->static_mb_pct == 100)) {
-          vp9_set_segdata(xd, 1, SEG_LVL_REF_FRAME, ALTREF_FRAME);
-          vp9_enable_segfeature(xd, 1, SEG_LVL_REF_FRAME);
-          vp9_enable_segfeature(xd, 1, SEG_LVL_SKIP);
+          vp9_set_segdata(&xd->seg, 1, SEG_LVL_REF_FRAME, ALTREF_FRAME);
+          vp9_enable_segfeature(&xd->seg, 1, SEG_LVL_REF_FRAME);
+          vp9_enable_segfeature(&xd->seg, 1, SEG_LVL_SKIP);
         }
       } else {
         // Disable segmentation and clear down features if alt ref
@@ -380,10 +380,10 @@
 
         vpx_memset(cpi->segmentation_map, 0, cm->mi_rows * cm->mi_cols);
 
-        xd->update_mb_segmentation_map = 0;
-        xd->update_mb_segmentation_data = 0;
+        xd->seg.update_map = 0;
+        xd->seg.update_data = 0;
 
-        vp9_clearall_segfeatures(xd);
+        vp9_clearall_segfeatures(&xd->seg);
       }
     } else if (cpi->is_src_frame_alt_ref) {
       // Special case where we are coding over the top of a previous
@@ -391,28 +391,28 @@
       // Segment coding disabled for compred testing
 
       // Enable ref frame features for segment 0 as well
-      vp9_enable_segfeature(xd, 0, SEG_LVL_REF_FRAME);
-      vp9_enable_segfeature(xd, 1, SEG_LVL_REF_FRAME);
+      vp9_enable_segfeature(&xd->seg, 0, SEG_LVL_REF_FRAME);
+      vp9_enable_segfeature(&xd->seg, 1, SEG_LVL_REF_FRAME);
 
       // All mbs should use ALTREF_FRAME
-      vp9_clear_segdata(xd, 0, SEG_LVL_REF_FRAME);
-      vp9_set_segdata(xd, 0, SEG_LVL_REF_FRAME, ALTREF_FRAME);
-      vp9_clear_segdata(xd, 1, SEG_LVL_REF_FRAME);
-      vp9_set_segdata(xd, 1, SEG_LVL_REF_FRAME, ALTREF_FRAME);
+      vp9_clear_segdata(&xd->seg, 0, SEG_LVL_REF_FRAME);
+      vp9_set_segdata(&xd->seg, 0, SEG_LVL_REF_FRAME, ALTREF_FRAME);
+      vp9_clear_segdata(&xd->seg, 1, SEG_LVL_REF_FRAME);
+      vp9_set_segdata(&xd->seg, 1, SEG_LVL_REF_FRAME, ALTREF_FRAME);
 
       // Skip all MBs if high Q (0,0 mv and skip coeffs)
       if (high_q) {
-          vp9_enable_segfeature(xd, 0, SEG_LVL_SKIP);
-          vp9_enable_segfeature(xd, 1, SEG_LVL_SKIP);
+          vp9_enable_segfeature(&xd->seg, 0, SEG_LVL_SKIP);
+          vp9_enable_segfeature(&xd->seg, 1, SEG_LVL_SKIP);
       }
       // Enable data udpate
-      xd->update_mb_segmentation_data = 1;
+      xd->seg.update_data = 1;
     } else {
       // All other frames.
 
       // No updates.. leave things as they are.
-      xd->update_mb_segmentation_map = 0;
-      xd->update_mb_segmentation_data = 0;
+      xd->seg.update_map = 0;
+      xd->seg.update_data = 0;
     }
   }
 }
@@ -2567,9 +2567,9 @@
     setup_features(cpi);
 
     // If segmentation is enabled force a map update for key frames
-    if (xd->segmentation_enabled) {
-      xd->update_mb_segmentation_map = 1;
-      xd->update_mb_segmentation_data = 1;
+    if (xd->seg.enabled) {
+      xd->seg.update_map = 1;
+      xd->seg.update_data = 1;
     }
 
     // The alternate reference frame cannot be active for a key frame
@@ -3100,9 +3100,8 @@
   cpi->dummy_packing = 0;
   vp9_pack_bitstream(cpi, dest, size);
 
-  if (xd->update_mb_segmentation_map) {
+  if (xd->seg.update_map)
     update_reference_segmentation_map(cpi);
-  }
 
   release_scaled_references(cpi);
   update_reference_frames(cpi);
@@ -3408,8 +3407,8 @@
   }
 
   // Clear the one shot update flags for segmentation map and mode/ref loop filter deltas.
-  xd->update_mb_segmentation_map = 0;
-  xd->update_mb_segmentation_data = 0;
+  xd->seg.update_map = 0;
+  xd->seg.update_data = 0;
   xd->mode_ref_lf_delta_update = 0;
 
   // keep track of the last coded dimensions
@@ -3521,8 +3520,8 @@
          cpi->refresh_alt_ref_frame ||
          cm->refresh_frame_context ||
          mb->mode_ref_lf_delta_update ||
-         mb->update_mb_segmentation_map ||
-         mb->update_mb_segmentation_data;
+         mb->seg.update_map ||
+         mb->seg.update_data;
 }
 
 #if CONFIG_MULTIPLE_ARF
@@ -3978,14 +3977,14 @@
   // Enable the loop and quant changes in the feature mask
   for (i = 0; i < MAX_MB_SEGMENTS; i++) {
     if (delta_q[i])
-      vp9_enable_segfeature(xd, i, SEG_LVL_ALT_Q);
+      vp9_enable_segfeature(&xd->seg, i, SEG_LVL_ALT_Q);
     else
-      vp9_disable_segfeature(xd, i, SEG_LVL_ALT_Q);
+      vp9_disable_segfeature(&xd->seg, i, SEG_LVL_ALT_Q);
 
     if (delta_lf[i])
-      vp9_enable_segfeature(xd, i, SEG_LVL_ALT_LF);
+      vp9_enable_segfeature(&xd->seg, i, SEG_LVL_ALT_LF);
     else
-      vp9_disable_segfeature(xd, i, SEG_LVL_ALT_LF);
+      vp9_disable_segfeature(&xd->seg, i, SEG_LVL_ALT_LF);
   }
 
   // Initialise the feature data structure
diff --git a/vp9/encoder/vp9_quantize.c b/vp9/encoder/vp9_quantize.c
index 862923f..2d3d6bf 100644
--- a/vp9/encoder/vp9_quantize.c
+++ b/vp9/encoder/vp9_quantize.c
@@ -365,7 +365,7 @@
   x->e_mbd.plane[3].dequant = cpi->common.a_dequant[qindex];
 #endif
 
-  x->skip_block = vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP);
+  x->skip_block = vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_SKIP);
 
   /* save this macroblock QIndex for vp9_update_zbin_extra() */
   x->e_mbd.q_index = qindex;
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index 93f8bb5..7339328 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -127,7 +127,7 @@
   vp9_copy(cc->uv_mode_prob, cm->fc.uv_mode_prob);
   vp9_copy(cc->partition_prob, cm->fc.partition_prob);
 
-  vp9_copy(cc->segment_pred_probs, cm->segment_pred_probs);
+  vp9_copy(cc->segment_pred_probs, xd->seg.pred_probs);
 
   vp9_copy(cc->intra_inter_prob, cm->fc.intra_inter_prob);
   vp9_copy(cc->comp_inter_prob, cm->fc.comp_inter_prob);
@@ -167,7 +167,7 @@
   vp9_copy(cm->fc.uv_mode_prob, cc->uv_mode_prob);
   vp9_copy(cm->fc.partition_prob, cc->partition_prob);
 
-  vp9_copy(cm->segment_pred_probs, cc->segment_pred_probs);
+  vp9_copy(xd->seg.pred_probs, cc->segment_pred_probs);
 
   vp9_copy(cm->fc.intra_inter_prob, cc->intra_inter_prob);
   vp9_copy(cm->fc.comp_inter_prob, cc->comp_inter_prob);
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index 4cb38f7..3982cf3 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -644,7 +644,7 @@
   pt = combine_entropy_contexts(above_ec, left_ec);
   nb = vp9_get_coef_neighbors_handle(scan);
 
-  if (vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP))
+  if (vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_SKIP))
     seg_eob = 0;
 
   /* sanity check to ensure that we do not have spurious non-zero q values */
@@ -1288,9 +1288,9 @@
                                                           block, 16),
                                       16, &ssz) >> 2;
 
-        if (best_tx_type != DCT_DCT)
+        if (tx_type != DCT_DCT)
           vp9_short_iht4x4_add(BLOCK_OFFSET(pd->dqcoeff, block, 16),
-                               dst, pd->dst.stride, best_tx_type);
+                               dst, pd->dst.stride, tx_type);
         else
           xd->inv_txm4x4_add(BLOCK_OFFSET(pd->dqcoeff, block, 16),
                              dst, pd->dst.stride);
@@ -1556,19 +1556,19 @@
   return best_rd;
 }
 
-static int cost_mv_ref(VP9_COMP *cpi,
-                       MB_PREDICTION_MODE m,
-                       const int mode_context) {
+static int cost_mv_ref(VP9_COMP *cpi, MB_PREDICTION_MODE mode,
+                       int mode_context) {
   MACROBLOCK *const x = &cpi->mb;
   MACROBLOCKD *const xd = &x->e_mbd;
-  int segment_id = xd->mode_info_context->mbmi.segment_id;
+  const int segment_id = xd->mode_info_context->mbmi.segment_id;
 
-  // Dont account for mode here if segment skip is enabled.
-  if (!vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP)) {
-    assert(NEARESTMV <= m  &&  m <= NEWMV);
-    return x->inter_mode_cost[mode_context][m - NEARESTMV];
-  } else
+  // Don't account for mode here if segment skip is enabled.
+  if (!vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_SKIP)) {
+    assert(is_inter_mode(mode));
+    return x->inter_mode_cost[mode_context][mode - NEARESTMV];
+  } else {
     return 0;
+  }
 }
 
 void vp9_set_mbmode_and_mvs(MACROBLOCK *x, MB_PREDICTION_MODE mb, int_mv *mv) {
@@ -2172,7 +2172,7 @@
                                      vp9_prob *comp_mode_p) {
   VP9_COMMON *const cm = &cpi->common;
   MACROBLOCKD *const xd = &cpi->mb.e_mbd;
-  int seg_ref_active = vp9_segfeature_active(xd, segment_id,
+  int seg_ref_active = vp9_segfeature_active(&xd->seg, segment_id,
                                              SEG_LVL_REF_FRAME);
   if (seg_ref_active) {
     vpx_memset(ref_costs_single, 0, MAX_REF_FRAMES * sizeof(*ref_costs_single));
@@ -3189,7 +3189,7 @@
     // Do not allow compound prediction if the segment level reference
     // frame feature is in use as in this case there can only be one reference.
     if ((vp9_mode_order[mode_index].second_ref_frame > INTRA_FRAME) &&
-         vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME))
+         vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_REF_FRAME))
       continue;
 
     x->skip = 0;
@@ -3271,9 +3271,9 @@
       set_scale_factors(xd, mbmi->ref_frame[0], mbmi->ref_frame[1],
                         scale_factor);
 
-      mode_excluded =
-          mode_excluded ?
-              mode_excluded : cm->comp_pred_mode == SINGLE_PREDICTION_ONLY;
+      mode_excluded = mode_excluded
+                         ? mode_excluded
+                         : cm->comp_pred_mode == SINGLE_PREDICTION_ONLY;
     } else {
       // mbmi->ref_frame[1] = vp9_mode_order[mode_index].ref_frame[1];
       if (ref_frame != INTRA_FRAME) {
@@ -3293,18 +3293,20 @@
 
     // If the segment reference frame feature is enabled....
     // then do nothing if the current ref frame is not allowed..
-    if (vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME) &&
-        vp9_get_segdata(xd, segment_id, SEG_LVL_REF_FRAME) != (int)ref_frame) {
+    if (vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_REF_FRAME) &&
+        vp9_get_segdata(&xd->seg, segment_id, SEG_LVL_REF_FRAME) !=
+            (int)ref_frame) {
       continue;
     // If the segment skip feature is enabled....
     // then do nothing if the current mode is not allowed..
-    } else if (vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP) &&
+    } else if (vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_SKIP) &&
                (this_mode != ZEROMV && ref_frame != INTRA_FRAME)) {
       continue;
     // Disable this drop out case if the ref frame
     // segment level feature is enabled for this segment. This is to
     // prevent the possibility that we end up unable to pick any mode.
-    } else if (!vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME)) {
+    } else if (!vp9_segfeature_active(&xd->seg, segment_id,
+                                      SEG_LVL_REF_FRAME)) {
       // Only consider ZEROMV/ALTREF_FRAME for alt ref frame,
       // unless ARNR filtering is enabled in which case we want
       // an unfiltered alternative
@@ -3579,10 +3581,9 @@
       // because there are no non zero coefficients and make any
       // necessary adjustment for rate. Ignore if skip is coded at
       // segment level as the cost wont have been added in.
-      int mb_skip_allowed;
-
       // Is Mb level skip allowed (i.e. not coded at segment level).
-      mb_skip_allowed = !vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP);
+      const int mb_skip_allowed = !vp9_segfeature_active(&xd->seg, segment_id,
+                                                         SEG_LVL_SKIP);
 
       if (skippable && bsize >= BLOCK_SIZE_SB8X8) {
         // Back out the coefficient coding costs
@@ -3881,7 +3882,7 @@
   // This code forces Altref,0,0 and skip for the frame that overlays a
   // an alrtef unless Altref is filtered. However, this is unsafe if
   // segment level coding of ref frame is enabled for this segment.
-  if (!vp9_segfeature_active(xd, segment_id, SEG_LVL_REF_FRAME) &&
+  if (!vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_REF_FRAME) &&
       cpi->is_src_frame_alt_ref &&
       (cpi->oxcf.arnr_max_frames == 0) &&
       (best_mbmode.mode != ZEROMV || best_mbmode.ref_frame[0] != ALTREF_FRAME)
diff --git a/vp9/encoder/vp9_segmentation.c b/vp9/encoder/vp9_segmentation.c
index fb2b23d..6a22df8 100644
--- a/vp9/encoder/vp9_segmentation.c
+++ b/vp9/encoder/vp9_segmentation.c
@@ -18,14 +18,14 @@
 void vp9_enable_segmentation(VP9_PTR ptr) {
   VP9_COMP *cpi = (VP9_COMP *)ptr;
 
-  cpi->mb.e_mbd.segmentation_enabled = 1;
-  cpi->mb.e_mbd.update_mb_segmentation_map = 1;
-  cpi->mb.e_mbd.update_mb_segmentation_data = 1;
+  cpi->mb.e_mbd.seg.enabled = 1;
+  cpi->mb.e_mbd.seg.update_map = 1;
+  cpi->mb.e_mbd.seg.update_data = 1;
 }
 
 void vp9_disable_segmentation(VP9_PTR ptr) {
   VP9_COMP *cpi = (VP9_COMP *)ptr;
-  cpi->mb.e_mbd.segmentation_enabled = 0;
+  cpi->mb.e_mbd.seg.enabled = 0;
 }
 
 void vp9_set_segmentation_map(VP9_PTR ptr,
@@ -37,8 +37,8 @@
              (cpi->common.mi_rows * cpi->common.mi_cols));
 
   // Signal that the map should be updated.
-  cpi->mb.e_mbd.update_mb_segmentation_map = 1;
-  cpi->mb.e_mbd.update_mb_segmentation_data = 1;
+  cpi->mb.e_mbd.seg.update_map = 1;
+  cpi->mb.e_mbd.seg.update_data = 1;
 }
 
 void vp9_set_segment_data(VP9_PTR ptr,
@@ -46,10 +46,10 @@
                           unsigned char abs_delta) {
   VP9_COMP *cpi = (VP9_COMP *)(ptr);
 
-  cpi->mb.e_mbd.mb_segment_abs_delta = abs_delta;
+  cpi->mb.e_mbd.seg.abs_delta = abs_delta;
 
-  vpx_memcpy(cpi->mb.e_mbd.segment_feature_data, feature_data,
-             sizeof(cpi->mb.e_mbd.segment_feature_data));
+  vpx_memcpy(cpi->mb.e_mbd.seg.feature_data, feature_data,
+             sizeof(cpi->mb.e_mbd.seg.feature_data));
 
   // TBD ?? Set the feature mask
   // vpx_memcpy(cpi->mb.e_mbd.segment_feature_mask, 0,
@@ -232,8 +232,8 @@
 
   // Set default state for the segment tree probabilities and the
   // temporal coding probabilities
-  vpx_memset(xd->mb_segment_tree_probs, 255, sizeof(xd->mb_segment_tree_probs));
-  vpx_memset(cm->segment_pred_probs, 255, sizeof(cm->segment_pred_probs));
+  vpx_memset(xd->seg.tree_probs, 255, sizeof(xd->seg.tree_probs));
+  vpx_memset(xd->seg.pred_probs, 255, sizeof(xd->seg.pred_probs));
 
   vpx_memset(no_pred_segcounts, 0, sizeof(no_pred_segcounts));
   vpx_memset(t_unpred_seg_counts, 0, sizeof(t_unpred_seg_counts));
@@ -283,11 +283,11 @@
 
   // Now choose which coding method to use.
   if (t_pred_cost < no_pred_cost) {
-    cm->temporal_update = 1;
-    vpx_memcpy(xd->mb_segment_tree_probs, t_pred_tree, sizeof(t_pred_tree));
-    vpx_memcpy(cm->segment_pred_probs, t_nopred_prob, sizeof(t_nopred_prob));
+    xd->seg.temporal_update = 1;
+    vpx_memcpy(xd->seg.tree_probs, t_pred_tree, sizeof(t_pred_tree));
+    vpx_memcpy(xd->seg.pred_probs, t_nopred_prob, sizeof(t_nopred_prob));
   } else {
-    cm->temporal_update = 0;
-    vpx_memcpy(xd->mb_segment_tree_probs, no_pred_tree, sizeof(no_pred_tree));
+    xd->seg.temporal_update = 0;
+    vpx_memcpy(xd->seg.tree_probs, no_pred_tree, sizeof(no_pred_tree));
   }
 }
diff --git a/vp9/encoder/vp9_tokenize.c b/vp9/encoder/vp9_tokenize.c
index c16bdff..d526990 100644
--- a/vp9/encoder/vp9_tokenize.c
+++ b/vp9/encoder/vp9_tokenize.c
@@ -180,7 +180,7 @@
   pt = combine_entropy_contexts(above_ec, left_ec);
   nb = vp9_get_coef_neighbors_handle(scan);
 
-  if (vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP))
+  if (vp9_segfeature_active(&xd->seg, segment_id, SEG_LVL_SKIP))
     seg_eob = 0;
 
   c = 0;
@@ -274,12 +274,10 @@
   MB_MODE_INFO * const mbmi = &xd->mode_info_context->mbmi;
   TOKENEXTRA *t_backup = *t;
   const int mb_skip_context = vp9_get_pred_context_mbskip(cm, xd);
-  const int segment_id = mbmi->segment_id;
-  const int skip_inc = !vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP);
+  const int skip_inc = !vp9_segfeature_active(&xd->seg, mbmi->segment_id,
+                                              SEG_LVL_SKIP);
   const TX_SIZE txfm_size = mbmi->txfm_size;
-  struct tokenize_b_args arg = {
-    cpi, xd, t, txfm_size, dry_run
-  };
+  struct tokenize_b_args arg = { cpi, xd, t, txfm_size, dry_run };
 
   mbmi->mb_skip_coeff = vp9_sb_is_skippable(xd, bsize);
 
diff --git a/vp9/encoder/x86/vp9_dct_mmx.asm b/vp9/encoder/x86/vp9_dct_mmx.asm
deleted file mode 100644
index 54766d8..0000000
--- a/vp9/encoder/x86/vp9_dct_mmx.asm
+++ /dev/null
@@ -1,241 +0,0 @@
-;
-;  Copyright (c) 2010 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_ports/x86_abi_support.asm"
-
-;void vp9_short_fdct4x4_mmx(short *input, short *output, int pitch)
-global sym(vp9_short_fdct4x4_mmx) PRIVATE
-sym(vp9_short_fdct4x4_mmx):
-    push        rbp
-    mov         rbp,        rsp
-    SHADOW_ARGS_TO_STACK 3
-    GET_GOT     rbx
-    push        rsi
-    push        rdi
-    ; end prolog
-
-        mov         rsi,        arg(0)      ; input
-        mov         rdi,        arg(1)      ; output
-
-        movsxd      rax,        dword ptr arg(2) ;pitch
-
-        lea         rcx,        [rsi + rax*2]
-        ; read the input data
-        movq        mm0,        [rsi]
-        movq        mm1,        [rsi + rax]
-
-        movq        mm2,        [rcx]
-        movq        mm4,        [rcx + rax]
-
-        ; transpose for the first stage
-        movq        mm3,        mm0         ; 00 01 02 03
-        movq        mm5,        mm2         ; 20 21 22 23
-
-        punpcklwd   mm0,        mm1         ; 00 10 01 11
-        punpckhwd   mm3,        mm1         ; 02 12 03 13
-
-        punpcklwd   mm2,        mm4         ; 20 30 21 31
-        punpckhwd   mm5,        mm4         ; 22 32 23 33
-
-        movq        mm1,        mm0         ; 00 10 01 11
-        punpckldq   mm0,        mm2         ; 00 10 20 30
-
-        punpckhdq   mm1,        mm2         ; 01 11 21 31
-
-        movq        mm2,        mm3         ; 02 12 03 13
-        punpckldq   mm2,        mm5         ; 02 12 22 32
-
-        punpckhdq   mm3,        mm5         ; 03 13 23 33
-
-        ; mm0 0
-        ; mm1 1
-        ; mm2 2
-        ; mm3 3
-
-        ; first stage
-        movq        mm5,        mm0
-        movq        mm4,        mm1
-
-        paddw       mm0,        mm3         ; a1 = 0 + 3
-        paddw       mm1,        mm2         ; b1 = 1 + 2
-
-        psubw       mm4,        mm2         ; c1 = 1 - 2
-        psubw       mm5,        mm3         ; d1 = 0 - 3
-
-        psllw       mm5,        3
-        psllw       mm4,        3
-
-        psllw       mm0,        3
-        psllw       mm1,        3
-
-        ; output 0 and 2
-        movq        mm2,        mm0         ; a1
-
-        paddw       mm0,        mm1         ; op[0] = a1 + b1
-        psubw       mm2,        mm1         ; op[2] = a1 - b1
-
-        ; output 1 and 3
-        ; interleave c1, d1
-        movq        mm1,        mm5         ; d1
-        punpcklwd   mm1,        mm4         ; c1 d1
-        punpckhwd   mm5,        mm4         ; c1 d1
-
-        movq        mm3,        mm1
-        movq        mm4,        mm5
-
-        pmaddwd     mm1,        MMWORD PTR[GLOBAL (_5352_2217)]    ; c1*2217 + d1*5352
-        pmaddwd     mm4,        MMWORD PTR[GLOBAL (_5352_2217)]    ; c1*2217 + d1*5352
-
-        pmaddwd     mm3,        MMWORD PTR[GLOBAL(_2217_neg5352)]  ; d1*2217 - c1*5352
-        pmaddwd     mm5,        MMWORD PTR[GLOBAL(_2217_neg5352)]  ; d1*2217 - c1*5352
-
-        paddd       mm1,        MMWORD PTR[GLOBAL(_14500)]
-        paddd       mm4,        MMWORD PTR[GLOBAL(_14500)]
-        paddd       mm3,        MMWORD PTR[GLOBAL(_7500)]
-        paddd       mm5,        MMWORD PTR[GLOBAL(_7500)]
-
-        psrad       mm1,        12          ; (c1 * 2217 + d1 * 5352 +  14500)>>12
-        psrad       mm4,        12          ; (c1 * 2217 + d1 * 5352 +  14500)>>12
-        psrad       mm3,        12          ; (d1 * 2217 - c1 * 5352 +   7500)>>12
-        psrad       mm5,        12          ; (d1 * 2217 - c1 * 5352 +   7500)>>12
-
-        packssdw    mm1,        mm4         ; op[1]
-        packssdw    mm3,        mm5         ; op[3]
-
-        ; done with vertical
-        ; transpose for the second stage
-        movq        mm4,        mm0         ; 00 10 20 30
-        movq        mm5,        mm2         ; 02 12 22 32
-
-        punpcklwd   mm0,        mm1         ; 00 01 10 11
-        punpckhwd   mm4,        mm1         ; 20 21 30 31
-
-        punpcklwd   mm2,        mm3         ; 02 03 12 13
-        punpckhwd   mm5,        mm3         ; 22 23 32 33
-
-        movq        mm1,        mm0         ; 00 01 10 11
-        punpckldq   mm0,        mm2         ; 00 01 02 03
-
-        punpckhdq   mm1,        mm2         ; 01 22 12 13
-
-        movq        mm2,        mm4         ; 20 31 30 31
-        punpckldq   mm2,        mm5         ; 20 21 22 23
-
-        punpckhdq   mm4,        mm5         ; 30 31 32 33
-
-        ; mm0 0
-        ; mm1 1
-        ; mm2 2
-        ; mm3 4
-
-        movq        mm5,        mm0
-        movq        mm3,        mm1
-
-        paddw       mm0,        mm4         ; a1 = 0 + 3
-        paddw       mm1,        mm2         ; b1 = 1 + 2
-
-        psubw       mm3,        mm2         ; c1 = 1 - 2
-        psubw       mm5,        mm4         ; d1 = 0 - 3
-
-        pxor        mm6,        mm6         ; zero out for compare
-
-        pcmpeqw     mm6,        mm5         ; d1 != 0
-
-        pandn       mm6,        MMWORD PTR[GLOBAL(_cmp_mask)]   ; clear upper,
-                                                                ; and keep bit 0 of lower
-
-        ; output 0 and 2
-        movq        mm2,        mm0         ; a1
-
-        paddw       mm0,        mm1         ; a1 + b1
-        psubw       mm2,        mm1         ; a1 - b1
-
-        paddw       mm0,        MMWORD PTR[GLOBAL(_7w)]
-        paddw       mm2,        MMWORD PTR[GLOBAL(_7w)]
-
-        psraw       mm0,        4           ; op[0] = (a1 + b1 + 7)>>4
-        psraw       mm2,        4           ; op[8] = (a1 - b1 + 7)>>4
-
-        movq        MMWORD PTR[rdi + 0 ],  mm0
-        movq        MMWORD PTR[rdi + 16],  mm2
-
-        ; output 1 and 3
-        ; interleave c1, d1
-        movq        mm1,        mm5         ; d1
-        punpcklwd   mm1,        mm3         ; c1 d1
-        punpckhwd   mm5,        mm3         ; c1 d1
-
-        movq        mm3,        mm1
-        movq        mm4,        mm5
-
-        pmaddwd     mm1,        MMWORD PTR[GLOBAL (_5352_2217)]    ; c1*2217 + d1*5352
-        pmaddwd     mm4,        MMWORD PTR[GLOBAL (_5352_2217)]    ; c1*2217 + d1*5352
-
-        pmaddwd     mm3,        MMWORD PTR[GLOBAL(_2217_neg5352)]  ; d1*2217 - c1*5352
-        pmaddwd     mm5,        MMWORD PTR[GLOBAL(_2217_neg5352)]  ; d1*2217 - c1*5352
-
-        paddd       mm1,        MMWORD PTR[GLOBAL(_12000)]
-        paddd       mm4,        MMWORD PTR[GLOBAL(_12000)]
-        paddd       mm3,        MMWORD PTR[GLOBAL(_51000)]
-        paddd       mm5,        MMWORD PTR[GLOBAL(_51000)]
-
-        psrad       mm1,        16          ; (c1 * 2217 + d1 * 5352 +  14500)>>16
-        psrad       mm4,        16          ; (c1 * 2217 + d1 * 5352 +  14500)>>16
-        psrad       mm3,        16          ; (d1 * 2217 - c1 * 5352 +   7500)>>16
-        psrad       mm5,        16          ; (d1 * 2217 - c1 * 5352 +   7500)>>16
-
-        packssdw    mm1,        mm4         ; op[4]
-        packssdw    mm3,        mm5         ; op[12]
-
-        paddw       mm1,        mm6         ; op[4] += (d1!=0)
-
-        movq        MMWORD PTR[rdi + 8 ],  mm1
-        movq        MMWORD PTR[rdi + 24],  mm3
-
-     ; begin epilog
-    pop         rdi
-    pop         rsi
-    RESTORE_GOT
-    UNSHADOW_ARGS
-    pop         rbp
-    ret
-
-SECTION_RODATA
-align 8
-_5352_2217:
-    dw 5352
-    dw 2217
-    dw 5352
-    dw 2217
-align 8
-_2217_neg5352:
-    dw 2217
-    dw -5352
-    dw 2217
-    dw -5352
-align 8
-_cmp_mask:
-    times 4 dw 1
-align 8
-_7w:
-    times 4 dw 7
-align 8
-_14500:
-    times 2 dd 14500
-align 8
-_7500:
-    times 2 dd 7500
-align 8
-_12000:
-    times 2 dd 12000
-align 8
-_51000:
-    times 2 dd 51000
diff --git a/vp9/encoder/x86/vp9_dct_mmx.h b/vp9/encoder/x86/vp9_dct_mmx.h
deleted file mode 100644
index 3bac7c8..0000000
--- a/vp9/encoder/x86/vp9_dct_mmx.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- *  Copyright (c) 2010 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 VP9_ENCODER_X86_VP9_DCT_MMX_H_
-#define VP9_ENCODER_X86_VP9_DCT_MMX_H_
-
-extern void vp9_short_fdct4x4_mmx(short *input, short *output, int pitch);
-
-
-#endif /* VP9_ENCODER_X86_VP9_DCT_MMX_H_ */
diff --git a/vp9/encoder/x86/vp9_fwalsh_sse2.asm b/vp9/encoder/x86/vp9_fwalsh_sse2.asm
deleted file mode 100644
index 7bee9ef..0000000
--- a/vp9/encoder/x86/vp9_fwalsh_sse2.asm
+++ /dev/null
@@ -1,164 +0,0 @@
-;
-;  Copyright (c) 2010 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_ports/x86_abi_support.asm"
-
-;void vp9_short_walsh4x4_sse2(short *input, short *output, int pitch)
-global sym(vp9_short_walsh4x4_sse2) PRIVATE
-sym(vp9_short_walsh4x4_sse2):
-    push        rbp
-    mov         rbp, rsp
-    SHADOW_ARGS_TO_STACK 3
-    SAVE_XMM 7
-    GET_GOT     rbx
-    push        rsi
-    push        rdi
-    ; end prolog
-
-    mov     rsi, arg(0)           ; input
-    mov     rdi, arg(1)           ; output
-    movsxd  rdx, dword ptr arg(2) ; pitch
-
-    ; first for loop
-    movq    xmm0, MMWORD PTR [rsi]           ; load input
-    movq    xmm1, MMWORD PTR [rsi + rdx]
-    lea     rsi,  [rsi + rdx*2]
-    movq    xmm2, MMWORD PTR [rsi]
-    movq    xmm3, MMWORD PTR [rsi + rdx]
-
-    punpcklwd xmm0,  xmm1
-    punpcklwd xmm2,  xmm3
-
-    movdqa    xmm1, xmm0
-    punpckldq xmm0, xmm2           ; ip[1] ip[0]
-    punpckhdq xmm1, xmm2           ; ip[3] ip[2]
-
-    movdqa    xmm2, xmm0
-    paddw     xmm0, xmm1
-    psubw     xmm2, xmm1
-
-    psllw     xmm0, 2              ; d1  a1
-    psllw     xmm2, 2              ; c1  b1
-
-    movdqa    xmm1, xmm0
-    punpcklqdq xmm0, xmm2          ; b1  a1
-    punpckhqdq xmm1, xmm2          ; c1  d1
-
-    pxor      xmm6, xmm6
-    movq      xmm6, xmm0
-    pxor      xmm7, xmm7
-    pcmpeqw   xmm7, xmm6
-    paddw     xmm7, [GLOBAL(c1)]
-
-    movdqa    xmm2, xmm0
-    paddw     xmm0, xmm1           ; b1+c1  a1+d1
-    psubw     xmm2, xmm1           ; b1-c1  a1-d1
-    paddw     xmm0, xmm7           ; b1+c1  a1+d1+(a1!=0)
-
-    ; second for loop
-    ; input: 13  9  5  1 12  8  4  0 (xmm0)
-    ;        14 10  6  2 15 11  7  3 (xmm2)
-    ; after shuffle:
-    ;        13  5  9  1 12  4  8  0 (xmm0)
-    ;        14  6 10  2 15  7 11  3 (xmm1)
-    pshuflw   xmm3, xmm0, 0xd8
-    pshufhw   xmm0, xmm3, 0xd8
-    pshuflw   xmm3, xmm2, 0xd8
-    pshufhw   xmm1, xmm3, 0xd8
-
-    movdqa    xmm2, xmm0
-    pmaddwd   xmm0, [GLOBAL(c1)]    ; d11 a11 d10 a10
-    pmaddwd   xmm2, [GLOBAL(cn1)]   ; c11 b11 c10 b10
-    movdqa    xmm3, xmm1
-    pmaddwd   xmm1, [GLOBAL(c1)]    ; d12 a12 d13 a13
-    pmaddwd   xmm3, [GLOBAL(cn1)]   ; c12 b12 c13 b13
-
-    pshufd    xmm4, xmm0, 0xd8      ; d11 d10 a11 a10
-    pshufd    xmm5, xmm2, 0xd8      ; c11 c10 b11 b10
-    pshufd    xmm6, xmm1, 0x72      ; d13 d12 a13 a12
-    pshufd    xmm7, xmm3, 0x72      ; c13 c12 b13 b12
-
-    movdqa    xmm0, xmm4
-    punpcklqdq xmm0, xmm5           ; b11 b10 a11 a10
-    punpckhqdq xmm4, xmm5           ; c11 c10 d11 d10
-    movdqa    xmm1, xmm6
-    punpcklqdq xmm1, xmm7           ; b13 b12 a13 a12
-    punpckhqdq xmm6, xmm7           ; c13 c12 d13 d12
-
-    movdqa    xmm2, xmm0
-    paddd     xmm0, xmm4            ; b21 b20 a21 a20
-    psubd     xmm2, xmm4            ; c21 c20 d21 d20
-    movdqa    xmm3, xmm1
-    paddd     xmm1, xmm6            ; b23 b22 a23 a22
-    psubd     xmm3, xmm6            ; c23 c22 d23 d22
-
-    pxor      xmm4, xmm4
-    movdqa    xmm5, xmm4
-    pcmpgtd   xmm4, xmm0
-    pcmpgtd   xmm5, xmm2
-    pand      xmm4, [GLOBAL(cd1)]
-    pand      xmm5, [GLOBAL(cd1)]
-
-    pxor      xmm6, xmm6
-    movdqa    xmm7, xmm6
-    pcmpgtd   xmm6, xmm1
-    pcmpgtd   xmm7, xmm3
-    pand      xmm6, [GLOBAL(cd1)]
-    pand      xmm7, [GLOBAL(cd1)]
-
-    paddd     xmm0, xmm4
-    paddd     xmm2, xmm5
-    paddd     xmm0, [GLOBAL(cd3)]
-    paddd     xmm2, [GLOBAL(cd3)]
-    paddd     xmm1, xmm6
-    paddd     xmm3, xmm7
-    paddd     xmm1, [GLOBAL(cd3)]
-    paddd     xmm3, [GLOBAL(cd3)]
-
-    psrad     xmm0, 3
-    psrad     xmm1, 3
-    psrad     xmm2, 3
-    psrad     xmm3, 3
-    movdqa    xmm4, xmm0
-    punpcklqdq xmm0, xmm1           ; a23 a22 a21 a20
-    punpckhqdq xmm4, xmm1           ; b23 b22 b21 b20
-    movdqa    xmm5, xmm2
-    punpckhqdq xmm2, xmm3           ; c23 c22 c21 c20
-    punpcklqdq xmm5, xmm3           ; d23 d22 d21 d20
-
-    packssdw  xmm0, xmm4            ; b23 b22 b21 b20 a23 a22 a21 a20
-    packssdw  xmm2, xmm5            ; d23 d22 d21 d20 c23 c22 c21 c20
-
-    movdqa  XMMWORD PTR [rdi], xmm0
-    movdqa  XMMWORD PTR [rdi + 16], xmm2
-
-    ; begin epilog
-    pop rdi
-    pop rsi
-    RESTORE_GOT
-    RESTORE_XMM
-    UNSHADOW_ARGS
-    pop         rbp
-    ret
-
-SECTION_RODATA
-align 16
-c1:
-    dw 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001
-align 16
-cn1:
-    dw 0x0001, 0xffff, 0x0001, 0xffff, 0x0001, 0xffff, 0x0001, 0xffff
-align 16
-cd1:
-    dd 0x00000001, 0x00000001, 0x00000001, 0x00000001
-align 16
-cd3:
-    dd 0x00000003, 0x00000003, 0x00000003, 0x00000003
diff --git a/vp9/vp9_common.mk b/vp9/vp9_common.mk
index 1079e20..2518ce1 100644
--- a/vp9/vp9_common.mk
+++ b/vp9/vp9_common.mk
@@ -75,10 +75,9 @@
 VP9_COMMON_SRCS-$(ARCH_X86)$(ARCH_X86_64) += common/x86/vp9_loopfilter_intrin_sse2.c
 VP9_COMMON_SRCS-$(CONFIG_POSTPROC) += common/vp9_postproc.h
 VP9_COMMON_SRCS-$(CONFIG_POSTPROC) += common/vp9_postproc.c
-VP9_COMMON_SRCS-$(HAVE_MMX) += common/x86/vp9_recon_mmx.asm
 VP9_COMMON_SRCS-$(HAVE_MMX) += common/x86/vp9_loopfilter_mmx.asm
+VP9_COMMON_SRCS-$(HAVE_SSE2) += common/x86/vp9_copy_sse2.asm
 VP9_COMMON_SRCS-$(HAVE_SSE2) += common/x86/vp9_loopfilter_sse2.asm
-VP9_COMMON_SRCS-$(HAVE_SSE2) += common/x86/vp9_recon_sse2.asm
 VP9_COMMON_SRCS-$(HAVE_SSE2) += common/x86/vp9_intrapred_sse2.asm
 VP9_COMMON_SRCS-$(HAVE_SSSE3) += common/x86/vp9_intrapred_ssse3.asm
 VP9_COMMON_SRCS-$(HAVE_SSSE3) += common/x86/vp9_subpixel_8t_ssse3.asm
@@ -89,6 +88,8 @@
 
 VP9_COMMON_SRCS-$(HAVE_SSE2) += common/x86/vp9_idct_intrin_sse2.c
 
+VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_convolve8_neon$(ASM)
 VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_loopfilter_neon$(ASM)
+VP9_COMMON_SRCS-$(HAVE_NEON) += common/arm/neon/vp9_dc_only_idct_add_neon$(ASM)
 
 $(eval $(call rtcd_h_template,vp9_rtcd,vp9/common/vp9_rtcd_defs.sh))
diff --git a/vp9/vp9cx.mk b/vp9/vp9cx.mk
index 12a49f8..dee83c9 100644
--- a/vp9/vp9cx.mk
+++ b/vp9/vp9cx.mk
@@ -78,13 +78,10 @@
 VP9_CX_SRCS-$(HAVE_MMX) += encoder/x86/vp9_variance_mmx.c
 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_MMX) += encoder/x86/vp9_dct_mmx.asm
-VP9_CX_SRCS-$(HAVE_MMX) += encoder/x86/vp9_dct_mmx.h
 VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_variance_sse2.c
 VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_variance_impl_sse2.asm
 VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_sad_sse2.asm
 VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_sad4d_sse2.asm
-VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_fwalsh_sse2.asm
 VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_subpel_variance.asm
 VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_subtract_sse2.asm
 VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_error_sse2.asm
diff --git a/vpx/internal/vpx_codec_internal.h b/vpx/internal/vpx_codec_internal.h
index d7bcd46..0b057de 100644
--- a/vpx/internal/vpx_codec_internal.h
+++ b/vpx/internal/vpx_codec_internal.h
@@ -94,9 +94,10 @@
 
 /*!\brief parse stream info function pointer prototype
  *
- * Performs high level parsing of the bitstream. This function is called by
- * the generic vpx_codec_parse_stream() wrapper function, so plugins implementing
- * this interface may trust the input parameters to be properly initialized.
+ * Performs high level parsing of the bitstream. This function is called by the
+ * generic vpx_codec_peek_stream_info() wrapper function, so plugins
+ * implementing this interface may trust the input parameters to be properly
+ * initialized.
  *
  * \param[in]      data    Pointer to a block of data to parse
  * \param[in]      data_sz Size of the data buffer
@@ -301,7 +302,7 @@
   vpx_codec_set_mmap_fn_t   set_mmap;    /**< \copydoc ::vpx_codec_set_mmap_fn_t */
   struct vpx_codec_dec_iface {
     vpx_codec_peek_si_fn_t    peek_si;     /**< \copydoc ::vpx_codec_peek_si_fn_t */
-    vpx_codec_get_si_fn_t     get_si;      /**< \copydoc ::vpx_codec_peek_si_fn_t */
+    vpx_codec_get_si_fn_t     get_si;      /**< \copydoc ::vpx_codec_get_si_fn_t */
     vpx_codec_decode_fn_t     decode;      /**< \copydoc ::vpx_codec_decode_fn_t */
     vpx_codec_get_frame_fn_t  get_frame;   /**< \copydoc ::vpx_codec_get_frame_fn_t */
   } dec;